Setups

Loading pacakges and custum functions

# loading packages
pacman::p_load(tidyverse, # tidy family and related pacakges below
               kableExtra, 
               gridExtra, 
               purrr,
               magrittr, # extending piping
               pander,   # nice tables
               metafor,  # package for meta-analysis
               MCMCglmm,  # Bayeisan mixed model package
               ggbeeswarm, # making bee-swarm plots possible
               plotly,     # interactive plots using ggplot2
               MuMIn,  # multi-model inference
               lme4,   # lmm & glmm (models)
               broom.mixed, # getting estimates from lmer + glmer objects
               performance, # getting R2 from lmer + glmer objects
               #lmerTest
               #mi,      # missing data analysis
               #betareg   # dependance of the above
)

# getting functions 
source("../R/ESM_functions.R", chdir = TRUE)

Custum functions

NOTE!!! We have XX custum functions: …….

Supplementary Methods and Materials

XXXX1

XXXX2

The Cophylogeny Dataset

Table of the dataset

Below is the dataset used for our meta-analysis follwed by explanations of 24 variables original collected (not all varaibles were used for our analyses; variables which were neither ‘directly’ nor ‘indirectly’ used in our analyses are indicated by *)

# getting the data and formating some variables (turning chraracter vectors
# to factors) read the difference between factr() and as.factor()
# <https://stackoverflow.com/questions/39279238/why-use-as-factor-instead-of-just-factor>
# full_data <- read.csv('../data/2019-04-04-source-data-dat.csv', na = 'NA',
# fileEncoding='UTF-8') %>% mutate_if(is.character, as.factor)
full_data <- read_csv("../data/2019-23-07-source-data-dat.csv", na = "NA") %>% 
    mutate_if(is.character, as.factor)

# making a scrollable table
kable(full_data, "html") %>% kable_styling("striped", position = "left") %>% 
    scroll_box(width = "100%", height = "500px")
authors year host_tax_broad host_tax_fine symbiont_tax_broad symbiont_tax_fine symbiont_euk symbiosis endo_or_ecto mode_of_transmission_broad mode_of_transmission_fine symbiont Visiting_symbiont? host_tips_linked host_tips_linked_corrected host_genera total_host_symbioint_links host_range_link_ratio host_range_taxonomic_breadth symbiont_tips_linked symbiont_genera no_randomizations p_value method
Xu_et_al_2017 2017 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Buchnera resident 20 20 8 20 1.00 1.00 20 1 1000 0.00100 TreeMap
Riess_et_al_2018 2018 Plant Fungus Microbe Fungus y Parasite Endo horizontal autonomous Root fungus resident 11 11 5 11 1.00 1.00 11 2 1000 0.33500 TreeMap
Badets_et_al_2011 2011 Vert Tetrapod Invert Invert y Parasite Endo horizontal autonomous Monogenea resident 17 17 13 17 1.00 1.00 17 4 1000 0.01000 TreeMap
Banks_et_al_2006 2006 Vert Bird Invert Invert y Parasite Ecto both contact Chewing lice resident 18 18 6 30 2.00 1.60 15 2 1000 0.01000 TreeMap
Bochkov_et_al_2011 2011 Vert Tetrapod Invert Invert y Parasite Ecto both contact Mites resident 6 6 NA 9 1.00 1.00 9 6 100 0.01000 TreeMap
Charleston_&_Perkins_2003 2003 Vert Tetrapod Microbe Protist y Parasite Endo horizontal vector Malaria resident 9 9 1 9 1.00 1.00 9 1 100 0.03000 TreeMap
Charleston_&_Robertson_2002 2002 Vert Tetrapod Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 12 12 12 12 1.00 1.00 12 1 1000 0.01500 TreeMap
Chauvatcharin_et_al_2006 2006 Microbe Bacterium Microbe Virus n Parasite Endo both NA Bacteriophage resident 14 14 7 15 1.07 1.00 14 1 1000 0.33100 TreeMap
Clark_et_al_2000 2000 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Buchnera resident 17 17 4 17 1.00 1.00 17 1 1000 0.00100 TreeMap
Clayton_&_Johnson_2003 2003 Vert Bird Invert Invert y Parasite Ecto both contact Dove body lice resident 13 13 6 14 1.08 1.15 13 1 10000 0.00060 TreeMap
Clayton_&_Johnson_2003 2003 Vert Bird Invert Invert y Parasite Ecto both contact Dove wing lice resident 13 13 6 16 1.60 1.50 10 1 10000 0.15300 TreeMap
Cui_et_al_2012 2012 Vert Tetrapod Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 7 7 3 7 1.00 1.00 7 7 10000 0.36600 TreeMap
Dabert_2001__ 2001 Vert Bird Invert Invert y Parasite Ecto both contact Feather mite resident 21 21 12 22 1.00 1.00 22 9 10000 0.00100 TreeMap
Deng_et_al_2013 2013 Invert Invert Invert Invert y Parasite Endo horizontal autonomous Parasitic wasps resident 7 7 4 10 1.00 1.43 10 2 999 0.53000 TreeMap
Desai_et_al_2010 2010 Microbe Protist Microbe Bacterium n Mutualist Ecto both contact Devescovinid flagellates resident 9 9 2 8 0.89 1.00 9 1 1000 0.00100 TreeMap
Desdevises_et_al_2002 2002 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Monogenea resident 14 14 11 39 1.95 1.45 20 2 999 0.31700 TreeMap
Downie_&_Gullan_2005 2005 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Primary endosymbiont Tremblaya resident 21 21 16 21 1.00 1.00 21 1 1000 0.00100 TreeMap
Erpenbeck_et_al_2002 2002 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Sponge symbiont resident 6 6 5 6 1.00 1.00 6 1 10000 0.02000 TreeMap
Etherington_et_al_2006 2006 Vert Tetrapod Microbe Virus n Parasite Endo horizontal contact Calicivirus resident 7 7 7 8 1.00 1.00 8 1 1000 0.01000 TreeMap
Farrell_1998 1998 Plant Plant Invert Invert y Parasite Ecto horizontal autonomous Cerambicid beetle resident 21 21 2 21 1.00 1.00 21 6 1000 0.07000 TreeMap
Gottschling_et_al_2011 2011 Vert Tetrapod Microbe Virus n Parasite Endo horizontal contact Papillomavirus resident 43 43 40 78 1.00 1.00 78 30 1000 0.00100 TreeMap
Hendricks_et_al_2013 2013 Vert Bird Invert Invert y Parasite Ecto both contact Quill mites resident 19 19 17 20 1.25 1.25 16 1 1000 0.02100 TreeMap
Hosokawa_et_al_2006 2006 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Gamma proteobacteria resident 7 7 3 7 1.00 1.00 7 1 1000 0.00100 TreeMap
Hugot_1999 1999 Vert Tetrapod Invert Invert y Parasite Endo horizontal trophic Pinworms resident 10 10 9 11 1.00 1.00 11 6 1000 0.00100 TreeMap
Hugot_et_al_2003 2003 Vert Tetrapod Microbe Fungus y Parasite Endo horizontal contact Pneumocystis resident 19 19 12 19 1.00 1.00 19 1 1000 0.00100 TreeMap
Huyse_&_Volckaert_2005 2005 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Gyrodactylus flatworms resident 8 8 3 22 1.29 1.24 17 1 100 0.02000 TreeMap
IkedaOhtsubo_&_Brune_2009 2009 Microbe Protist Microbe Bacterium n Mutualist Ecto vertical vertical Endomicrobium resident 11 11 1 11 1.00 1.00 11 1 1000 0.00100 TreeMap
Jackson_&_Charleston_1994 1994 Vert Tetrapod Microbe Virus n Parasite Endo horizontal contact Lyssavirus resident 10 10 8 10 1.00 1.00 10 1 100 0.19000 TreeMap
Jackson_&_Charleston_1994 1994 Vert Tetrapod Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 10 10 7 10 1.00 1.00 10 1 100 0.01000 TreeMap
Jackson_&_Charleston_1994 1994 Vert Tetrapod Microbe Virus n Parasite Endo horizontal contact Arenavirus resident 11 11 7 12 1.00 1.00 12 1 100 0.05000 TreeMap
Jackson_&_Charleston_1994 1994 Vert Bird Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 13 13 9 15 1.00 1.00 15 1 100 0.18000 TreeMap
Jackson_&_Charleston_1994 1994 Vert Tetrapod Microbe Virus n Parasite Endo horizontal contact Hantavirus resident 14 14 7 17 1.00 1.00 17 1 100 0.01000 TreeMap
Jeong_et_al_1999 1999 Plant Plant Microbe Bacterium n Mutualist Endo horizontal vector Frankia resident 12 12 12 19 1.06 1.00 18 1 1000 0.23000 TreeMap
Johnson_et_al_2002 2002 Vert Bird Invert Invert y Parasite Ecto both contact Bird louse resident 25 25 23 25 1.32 1.42 19 19 1000 0.23000 TreeMap
Johnson_et_al_2003 2003 Vert Bird Invert Invert y Parasite Ecto both contact Dove wing lice resident 28 28 15 31 1.48 1.33 21 1 100 0.03000 TreeMap
Johnson_et_al_2006 2006 Vert Bird Invert Invert y Parasite Ecto both contact Flamingo lice resident 10 10 NA 11 1.00 1.00 11 11 1000 0.40200 TreeMap
Jousselin_et_al_2008 2009 Plant Plant Invert Invert y Mutualist Endo horizontal autonomous Fig wasp resident 15 15 1 15 1.07 1.07 14 6 10000 0.01000 TreeMap
Jousselin_et_al_2008 2009 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Fig wasp resident 13 13 1 14 1.00 1.00 14 1 10000 0.01000 TreeMap
Jousselin_et_al_2008 2009 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Fig wasp resident 13 13 1 13 1.00 1.00 13 1 10000 0.01000 TreeMap
Jousselin_et_al_2008 2009 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Fig wasp resident 16 16 1 18 1.06 1.06 17 2 10000 0.01000 TreeMap
Jousselin_et_al_2009 2009 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Buchnera resident 55 22 1 22 1.00 1.00 22 1 10000 0.00100 TreeMap
Kawaida_et_al_2013 2013 Invert Invert Plant Plant y Mutualist Endo vertical vertical Green algae resident 6 6 1 6 1.00 1.00 6 1 10000 0.00350 TreeMap
Kawakita_et_al_2004 2004 Plant Plant Invert Invert y Mutualist Ecto horizontal autonomous Pollinating moth visitor 18 18 1 18 1.00 1.00 18 1 999 0.01900 TreeMap
Kelley_&_Farrell_1998 1998 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Bark beetle resident 41 41 1 89 6.85 1.92 13 1 100 0.28000 TreeMap
Kikuchi_et_al_2009 2009 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Gut symbiont resident 14 14 5 14 1.00 1.00 14 1 1000 0.00100 TreeMap
Lanterbecq_et_al_2010 2010 Invert Invert Invert Invert y Parasite Endo/Ecto horizontal contact Myzostomid worm resident 16 16 12 16 1.00 1.00 16 5 5000 0.04000 TreeMap
Light_&_Hafner_2008 2008 Vert Tetrapod Invert Invert y Parasite Ecto both contact Rodent sucking lice resident 44 21 4 21 1.00 1.00 21 1 1000 0.00100 TreeMap
LimFong_et_al_2008 2008 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Endobugula bacteria resident 5 5 1 5 1.00 1.00 5 2 1000 0.11000 TreeMap
Liu_et_al_2013 2013 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Buchnera resident 37 37 1 37 1.00 1.00 37 1 1000 0.00100 TreeMap
Liu_et_al_2014 2014 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Buchnera resident 27 27 3 29 1.00 1.00 29 1 1000 0.01000 TreeMap
LopezVaamonde_et_al_2001 2001 Invert Invert Invert Invert y Parasite Endo horizontal autonomous Figwasp resident 15 15 1 15 1.00 1.00 15 1 1000 0.00100 TreeMap
LopezVaamonde_et_al_2003 2003 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Leaf mining moth resident 33 33 33 77 1.00 1.00 77 1 1000 0.21300 TreeMap
LopezVaamonde_et_al_2005 2005 Invert Invert Invert Invert y Parasite Endo horizontal autonomous Parasitic wasp resident 28 28 1 35 2.33 1.33 15 1 1000 0.24800 TreeMap
Martin_et_al_1999 1999 Vert Tetrapod Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 38 38 38 48 1.00 1.00 48 1 1000 0.00100 TreeMap
Martin_et_al_2003 2003 Vert Bird Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 14 14 14 16 1.00 1.00 16 1 100 0.01000 TreeMap
Martin_et_al_2003 2003 Vert Tetrapod Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 9 9 9 9 1.00 1.00 9 1 100 0.05000 TreeMap
Martin_et_al_2003 2003 Vert Tetrapod Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 17 17 17 23 1.00 1.00 23 1 100 0.21000 TreeMap
Mazzon_et_al_2010 2010 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Stammerula resident 17 17 10 17 1.06 1.13 16 3 1000 0.00100 TreeMap
Morelli_&_Spicer_2007 2007 Vert Bird Invert Invert y Parasite Ecto both contact Bird nasal mite resident 6 6 6 6 1.00 1.00 6 1 10000 0.00950 TreeMap
Muniz_et_al_2013 2013 Vert Tetrapod Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 17 17 11 17 1.00 1.00 17 1 10000 0.00001 TreeMap
Musser_et_al_2010 2010 Vert Mammal Invert Invert y Parasite Ecto both contact Squirrel sucking lice resident 6 6 1 6 1.00 1.00 6 6 100 0.30000 TreeMap
Pagan_et_al_2010 2010 Plant Plant Microbe Virus n Parasite Endo horizontal contact Tobamovirus resident 10 10 10 13 1.00 1.00 13 1 1000 0.24000 TreeMap
Page_1996 1996 Vert Tetrapod Invert Invert y Parasite Ecto both contact Gopher chewing lice resident 15 15 6 17 1.00 1.00 17 2 1000 0.00100 TreeMap
Page_et_al_1998 1998 Vert Bird Invert Invert y Parasite Ecto both contact Bird lice resident 7 7 1 8 1.00 1.00 8 1 100 0.01000 TreeMap
Page_et_al_2004 2004 Vert Bird Invert Invert y Parasite Ecto both contact Seabird lice resident 12 12 4 12 1.00 1.00 12 1 1000 0.00100 TreeMap
Page_et_al_2004 2004 Vert Bird Invert Invert y Parasite Ecto both contact Seabird lice resident 11 11 5 13 1.00 1.00 13 4 100 0.25000 TreeMap
Page_et_al_2004 2004 Vert Bird Invert Invert y Parasite Ecto both contact Seabird lice resident 13 13 5 14 1.00 1.00 14 1 100 0.46000 TreeMap
Page_et_al_2004 2004 Vert Bird Invert Invert y Parasite Ecto both contact Seabird lice resident 9 9 3 9 1.00 1.00 9 1 100 0.36000 TreeMap
Paterson_&_Poulin_1999 1999 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Parasitic copepod resident 8 8 8 12 1.20 2.20 10 1 100 0.01000 TreeMap
Paterson_et_al_2000 2000 Vert Bird Invert Invert y Parasite Ecto both contact Seabird lice resident 11 11 5 14 1.00 1.00 14 5 100 0.01000 TreeMap
Percy_et_al_2004 2004 Plant Plant Invert Invert y Parasite Ecto both autonomous Psyllid resident 35 35 8 56 1.22 1.09 46 4 1000 0.00500 TreeMap
PerezLosada_et_al_2006 2006 Vert Tetrapod Microbe Virus n Parasite Endo horizontal NA Polyomavirus resident 9 9 9 11 1.00 1.00 11 1 100 0.01000 TreeMap
Perlman_et_al_2003 2003 Invert Invert Invert Invert y Parasite Endo horizontal autonomous Nematode resident 16 16 1 17 1.89 1.33 9 1 1000 0.14000 TreeMap
Quek_et_al_2004 2004 Plant Plant Invert Invert y Mutualist Ecto horizontal autonomous Ants resident 11 11 1 23 2.30 1.60 10 1 1000 0.99900 TreeMap
Ramsden_et_al_2008 2008 Vert Tetrapod Microbe Virus n Parasite Endo horizontal contact Hantavirus resident 33 33 20 38 1.00 1.00 38 1 1000 0.99900 TreeMap
Reed_et_al_2007 2007 Vert Tetrapod Invert Invert y Parasite Ecto horizontal contact Anthropoid lice resident 4 4 4 6 1.20 1.00 5 4 1000 0.05000 TreeMap
Refregier_et_al_2008 2008 Plant Plant Microbe Fungus y Parasite Endo horizontal vector Anther smut fungi resident 18 18 7 20 1.25 1.25 16 1 3000 0.50000 TreeMap
Shoemaker_et_al_2002 2002 Invert Invert Microbe Bacterium n Mutualist Endo both NA Wolbachia resident 20 20 7 23 1.00 1.00 23 1 100 0.47000 TreeMap
Simkova_et_al_2013 2013 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Monogenea resident 5 5 1 21 1.00 1.00 21 1 999 0.04500 TreeMap
Six_&_Paine_1999 1999 Microbe Fungus Invert Invert y Mutualist Ecto horizontal vector Mycangial fungi resident 6 6 1 6 1.00 1.00 6 3 1000 0.03100 TreeMap
Skerikova_et_al_2001 2001 Vert Fish Invert Invert y Parasite Endo horizontal trophic Cestode resident 7 7 7 7 1.00 1.00 7 1 10000 0.40000 TreeMap
Smith_et_al_2008b 2008 Vert Tetrapod Invert Invert y Parasite Ecto both contact Rodent lice resident 20 20 3 20 1.00 1.00 20 14 100 0.05000 TreeMap
Sorenson_et_al_2004 2004 Vert Bird Vert Bird y Parasite Ecto horizontal autonomous Brood parasitic finch resident 33 33 10 34 1.62 1.43 21 1 100 0.15000 TreeMap
Subbotin_et_al_2004 2004 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Nematode resident 16 16 16 21 1.00 1.00 21 4 1000 0.00100 TreeMap
Switzer_et_al_2005 2005 Vert Tetrapod Microbe Virus n Parasite Endo horizontal bodily fluid Retrovirus resident 46 46 17 51 1.00 1.00 51 1 10000 0.00700 TreeMap
Urban_&_Cryan_2012 2012 Invert Invert Microbe Bacterium n Mutualist Endo vertical autonomous Fulgorid planthopper microbe resident 40 40 38 40 1.00 1.00 40 1 1000 0.00100 TreeMap
Urban_&_Cryan_2012 2012 Invert Invert Microbe Bacterium n Mutualist Endo vertical autonomous Fulgorid planthopper microbe resident 30 30 29 30 1.00 1.00 30 1 1000 0.00100 TreeMap
Vanhove_et_al_2015 2015 Vert Fish Invert Invert y Parasite Endo horizontal autonomous Monogenea resident 19 19 10 28 1.00 1.00 28 1 10000 0.04210 TreeMap
Weckstein_2004 2004 Vert Bird Invert Invert y Parasite Ecto both contact Toucan chewing lice resident 11 11 1 11 2.20 1.80 5 1 10000 0.89000 TreeMap
Weiblen_&_Bush_2002 2002 Plant Plant Invert Invert y Mutualist Endo horizontal autonomous Fig wasp resident 19 19 1 19 1.00 1.00 19 1 10000 0.01950 TreeMap
Weiblen_&_Bush_2002 2002 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Fig wasp resident 12 12 1 18 1.00 1.00 18 1 10000 0.12150 TreeMap
Wu_et_al_2008 2008 Plant Plant Microbe Virus n Parasite Endo horizontal vector Mastrevirus resident 8 8 8 10 1.00 1.00 10 1 100 0.01000 TreeMap
Yan_et_al_2011 2011 Vert Fish Microbe Virus n Parasite Endo horizontal contact Lymphocystis resident 8 8 8 15 1.00 1.00 15 1 999 0.98900 TreeMap
Riess_et_al_2018 2018 Plant Fungus Microbe Fungus y Parasite Endo horizontal autonomous Root fungus resident 11 11 5 11 1.00 1.00 11 2 9999 0.26400 Parafit
Souza_et_al_2018 2018 Vert Mammal Microbe Virus n Parasite Endo both bodily fluid Primate hepadnaviruses resident 8 8 8 19 1.06 1.00 18 1 999 0.00500 Parafit
Ramasindrazana_et_al_2017 2017 Vert Mammal Invert Invert y Parasite Ecto both contact Bat flies (Nycteribiidae) resident 15 15 6 26 2.89 1.78 9 5 999 0.00100 Parafit
Li_et_al_2017 2017 Plant Plant Microbe Fungus y Parasite Endo horizontal vector Grass fungus (Tranzscheliella) Resident 12 12 9 12 1.71 2.00 7 1 999 0.50505 Parafit
Sweet_et_al_2018b 2018 Vert Bird Invert Invert y Parasite Ecto both contact body lice (Physconelloides) resident 11 11 4 13 1.86 1.43 7 1 100000 0.00500 Parafit
Sweet_&_Johnson_2018 2018 Vert Bird Invert Invert y Parasite Ecto both contact wing lice (Columbicola) resident 13 13 4 14 2.80 1.80 5 1 100000 0.00500 Parafit
Arab_et_al_2019 2019 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Blattabacterium of cockroaches resident 55 55 52 55 1.00 1.00 55 1 999 0.00100 Parafit
Sweet_et_al_2018a 2018 Vert Bird Invert Invert y Parasite Ecto both contact Brueelia bird lice resident 259 259 163 283 1.63 1.61 174 11 9999 0.00010 Parafit
Hewitt_et_al_2019 2019 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Unionid mussels resident 178 178 79 495 7.17 3.30 69 35 999 0.00100 Parafit
Latinne_et_al_2018 2018 Vert Mammal Microbe Funus y Parasite Endo horizontal enviromental Pneumocystis of rodents resident 15 15 6 19 3.17 2.00 6 1 999 0.00900 Parafit
Graca_et_al_2018 2018 Vert Fish Invert Invert y Parasite Endo horizontal autonomous Monogenea resident 9 9 7 18 1.29 1.29 14 1 10000 0.00010 Parafit
Sweet_et_al_2017 2017 Vert Bird Invert Invert y Parasite Ecto both contact Phabine bird lice resident 12 12 5 15 1.15 1.23 13 3 999 0.06900 Parafit
Zhang_et_al_2017 2017 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Nardonella of Weevils resident 44 44 24 44 1.00 1.00 44 1 100000 0.00001 Parafit
Megia-palma_et_al_2018 2018 Vert Reptile Microbe Protist y Parasite Endo horizontal vector Lizard Schellackia Apicomplexa resident 16 16 8 23 1.53 1.27 15 8 999 0.00400 Parafit
Dona_2018 2018 Vert Bird Invert Invert y Parasite Ecto both contact Trouessartia Feather mite resident 14 14 13 15 1.00 1.00 15 1 100000 0.01000 Parafit
Dona_2018 2018 Vert Bird Invert Invert y Parasite Ecto both contact Proctophyllodes Feather mite resident 42 42 29 44 1.00 1.00 44 1 100000 0.01000 Parafit
Xu_et_el_2017 2017 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Buchner resident 20 20 8 20 1.00 1.00 20 1 999 0.00100 Parafit
Chen_et_al_2017 2017 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Buchnera resident 50 50 11 50 1.00 1.00 50 1 999 0.00100 Parafit
Patra_et_al_2018 2018 Vert Fish Invert Invert y Parasite Endo horizontal environmental Myxozoa resident 24 24 24 31 1.00 1.00 31 1 999 0.00100 Parafit
Matthews_et_al_2018 2018 Vert Bird Invert Invert y Parasite Ecto both contact Amerodectes feather mites resident 12 12 6 33 1.00 0.58 33 1 99900 0.00400 Parafit
Catanach_et_al_2018 2018 Vert Bird Invert Invert y Parasite Ecto both contact Colpocephalum resident 54 28 5 44 1.07 0.93 41 30 999 0.00100 Parafit
Ballinger_et_al_2018 2018 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Spiroplasma resident 11 11 1 12 1.00 1.00 12 1 999 0.07000 Parafit
Li_et_al_2018 2018 Vert Vert Invert Invert y Parasite Endo horizontal trophic Ascarid worms resident 68 68 34 129 1.45 NA 89 89 100000 0.00100 Parafit
Holzer_et_al_2018 2018 Invert Invert Invert Invert y Parasite Endo horizontal environmental Myxozoa resident 23 23 22 39 1.00 1.00 39 21 1000 0.00100 Parafit
Holzer_et_al_2018 2018 Vert Fish Invert Invert y Parasite Endo horizontal environmental Myxozoa FW (OIM) resident 69 69 62 101 1.00 1.00 101 15 1000 0.00100 Parafit
Holzer_et_al_2018 2018 Vert Fish Invert Invert y Parasite Endo horizontal environmental Myxozoa (PIM) resident 69 69 58 75 1.00 1.00 75 21 1000 0.00100 Parafit
Carneiro_et_al_2018 2018 Vert Mammal Microbe Virus n Parasite Endo horizontal bodily fluid Hepatovirus resident 26 26 21 26 1.00 1.00 26 1 100000 0.01000 Parafit
Jesovnik_et_al_2017 2017 Invert Invert Microbe Fungus y Mutualist Ecto both environmental Ant fungus resident 32 6 1 6 1.00 1.00 6 1 999 0.02900 Parafit
Singh_et_al_2017 2017 Microbe Fungus Plant Plant y Mutualist Endo vertical vertical Lichen algae resident 23 17 1 25 1.25 1.15 20 1 9999 0.00020 Parafit
Endara_et_al_2018 2018 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Sawfly resident 44 30 1 45 1.18 1.03 38 NA 9999 0.01500 Parafit
Endara_et_al_2017 2017 Plant Plant Invert Invert y Parasite Ecto horizontal autonomous Gelechioidea moths visitor 18 18 1 29 1.00 2.17 29 NA 100 0.70000 Parafit
Endara_et_al_2017 2017 Plant Plant Invert Invert y Parasite Ecto horizontal autonomous Riodinidae moths visitor 10 10 1 18 1.50 1.25 12 NA 100 0.90000 Parafit
Endara_et_al_2017 2017 Plant Plant Invert Invert y Parasite Ecto horizontal autonomous Erebidae moths visitor 14 14 1 18 1.20 1.13 15 NA 100 0.74000 Parafit
Lauber_et_al_2017 2017 Vert Vert Microbe Virus n Parasite Endo horizontal autonomous Nackednaviruses and Hepadnaviruses resident 30 30 28 30 0.88 1.00 34 8 10000 0.00010 Parafit
Althoff_et_al_2012 2012 Plant Plant Invert Invert y Mutualist Ecto horizontal autonomous Yucca moth visitor 24 24 1 40 2.00 1.35 20 1 1000 0.00100 Parafit
Althoff_et_al_2012 2012 Plant Plant Invert Invert y Mutualist Ecto horizontal autonomous Yucca moth visitor 24 24 1 38 2.24 1.53 17 1 1000 0.00100 Parafit
Banks_et_al_2006 2006 Vert Bird Invert Invert y Parasite Ecto both contact Penguin chewing lice resident 18 18 6 30 2.00 1.60 15 2 10000 0.00100 Parafit
Bayerlova_2009 2009 Vert Mammal Microbe Virus n Parasite Endo horizontal contact Arenavirus resident 21 21 14 31 1.55 1.45 20 1 9999 0.00040 Parafit
Bellec_et_al_2014 2014 Plant Plant Microbe Virus n Parasite Endo horizontal contact Prasinovirus resident 22 22 3 133 2.61 1.65 51 1 999 0.00100 Parafit
Bruyndonckxx_et_al_2009 2009 Vert Mammal Invert Invert y Parasite Ecto both contact Bat mites resident 20 20 7 21 1.91 2.27 11 2 9999 0.00300 Parafit
Caraguel_et_al__2007 2007 Microbe Amoeba Microbe Protist y Mutualist Endo vertical vertical Prokinetoplastid endosymbiont resident 6 6 1 6 1.00 1.00 6 1 9999 0.00100 Parafit
Choi_&_Thines_2015 2015 Plant Plant Microbe Fungus y Parasite Endo horizontal autonomous Downy mildew resident 63 63 28 63 1.00 1.00 63 3 999 0.00100 Parafit
Conord_et_al_2008 2008 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Dryophthoridae endosymbionts resident 14 14 10 14 1.00 1.00 14 1 999 0.00900 Parafit
Cornuault_et_al_2012 2012 Vert Bird Microbe Protist y Parasite Endo horizontal vector Leucocytozoon resident 8 8 1 23 1.28 1.17 18 1 9999 0.03500 Parafit
Cruaud_et_al_2012 2012 Plant Plant Invert Invert y Mutualist Endo horizontal autonomous Fig wasp resident 200 200 1 200 1.00 1.00 200 20 9999 0.01000 Parafit
Cui_et_al_2014 2014 Vert Bird Microbe Virus n Parasite Endo horizontal bodily fluid Hepadnavirus resident 46 46 46 NA NA NA 61 NA 99999 0.23300 Parafit
Deng_et_al_2013 2013 Invert Invert Invert Invert y Parasite Endo horizontal autonomous Parasitic wasp resident 7 7 4 10 1.00 1.00 10 2 999 0.01602 Parafit
Desdevises_et_al_2002 2002 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Monogenea resident 14 14 11 39 2.00 1.65 20 2 999 0.26000 Parafit
Dhami_et_al_2013 2013 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Hoataupuhia symbiont resident 42 42 NA 42 1.00 1.00 42 4 999 0.00100 Parafit
Dowie_et_al_2016 2016 Microbe Fungus Plant Plant y Parasite Endo horizontal environmental Parasitic plant resident 4 4 1 9 2.25 1.50 4 1 9999 0.00100 Parafit
Du_Toit_et_al_2013 2013 Vert Mammal Invert Invert y Parasite Ecto both contact Rodent lice resident 4 4 1 14 1.17 1.17 12 1 10000 0.88000 Parafit
FerrerParis_et_al_2013 2013 Plant Plant Invert Invert y Parasite Ecto horizontal autonomous Butterflies visitor 64 64 NA 112 2.73 5.20 41 NA 999 0.15700 Parafit
FraijaFernandez_et_al_2016 2016 Vert Mammal Invert Invert y Parasite Endo horizontal trophic Digenea resident 31 31 24 50 5.56 3.67 9 6 999 0.00100 Parafit
Garamszegi_2009 2009 Vert Mammal Microbe Protist y Parasite Endo horizontal vector Primate malaria resident 23 23 23 43 2.39 2.56 18 1 1000 0.00100 Parafit
Garcia_&_Hayman_2016 2016 Vert Vert Microbe Protist y Parasite Endo horizontal trophic Cryptosporidium resident 22 22 22 36 1.33 1.96 27 1 999 0.01000 Parafit
Gavotte_et_al_2007 2007 Microbe Bacterium Microbe Virus n Parasite Endo both NA Bacteriophage resident 33 33 1 51 0.93 1.00 55 1 10000 0.13190 Parafit
Goker_et_al_2011 2011 Microbe Fungus Microbe Virus n Parasite Endo NA NA Mycovirus resident 8 8 8 8 1.00 1.00 8 1 9999 0.09780 Parafit
Gomard_et_al_2016 2016 Vert Mammal Microbe Bacterium n Parasite Endo horizontal NA Leptospira resident 12 12 11 26 1.00 1.00 26 1 999 0.09000 Parafit
Gottschling_et_al_2011 2011 Vert Mammal Microbe Virus n Parasite Endo horizontal contact Papillomavirus resident 43 43 40 76 0.97 1.00 78 30 9999 0.00010 Parafit
Hall_et_al__2016 2016 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Carsonella primary endosymbiont resident 37 37 18 37 1.00 1.00 37 1 10000 0.00100 Parafit
Hall_et_al__2016 2016 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Arsenophonus secondary endosymbiont resident 20 20 9 20 1.00 1.00 20 1 10000 0.38700 Parafit
Hammer_et_al_2010 2010 Vert Bird Invert Invert y Parasite Ecto both contact Petrel chewing lice resident 23 23 6 23 1.10 1.00 21 1 999 0.00100 Parafit
Hammerlinck_et_al_2016 2016 Invert Invert Invert Invert y Parasite Endo horizontal autonomous Parasitic wasp resident 11 11 2 11 1.38 1.13 8 2 999 0.12900 Parafit
Hammerlinck_et_al_2016 2016 Invert Invert Invert Invert y Parasite Endo horizontal autonomous Parasitic wasp resident 6 6 2 6 1.50 1.25 4 2 999 0.19500 Parafit
Hammerlinck_et_al_2016 2016 Invert Invert Invert Invert y Parasite Endo horizontal autonomous Parasitic wasp resident 7 7 2 7 1.00 1.00 7 2 999 0.04200 Parafit
Hembry_et_al_2013 2013 Plant Plant Invert Invert y Mutualist Ecto horizontal autonomous Pollinating moths visitor 37 37 1 35 1.00 1.00 35 1 999 0.01700 Parafit
Herrera__et_al_2016 2016 Microbe Fungus Microbe Fungus y Parasite Endo horizontal environmental Mycoparasite Cosmospora resident 13 13 9 13 1.00 1.00 13 3 999 0.00500 Parafit
Hoglund_et_al_2003 2003 Vert Vert Invert Invert y Parasite Endo horizontal trophic Lungworm resident 8 8 8 10 2.00 2.40 5 1 10000 0.09800 Parafit
Hughes_et_al_2007 2007 Vert Bird Invert Invert y Parasite Ecto both contact Pelican lice resident 18 18 6 18 1.06 1.00 17 1 999 0.00010 Parafit
Huyse_&_Volckaert_2005 2005 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Monogenea resident 8 8 5 22 1.29 1.29 17 1 999 0.09500 Parafit
Irwin_et_al_2012 2012 Vert Mammal Microbe Virus n Parasite Endo horizontal contact Arenavirus resident 21 21 14 31 1.55 1.85 20 NA 9999 0.00040 Parafit
Jenkins_et_al_2012 2012 Vert Bird Microbe Protist y Parasite Endo horizontal autonomous Leucocytozoon resident 52 52 40 138 1.45 NA 95 1 999 0.00100 Parafit
Jousselin_et_al_2008 2008 Plant Plant Invert Invert y Mutualist Endo horizontal autonomous Fig wasp resident 15 15 1 15 1.07 1.07 14 6 9999 0.00300 Parafit
Jousselin_et_al_2008 2008 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Fig wasp resident 13 13 1 13 1.00 1.00 13 1 9999 0.02000 Parafit
Jousselin_et_al_2008 2008 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Fig wasp resident 16 16 1 18 1.06 1.06 17 2 9999 0.00100 Parafit
Jousselin_et_al_2008 2008 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Fig wasp resident 13 13 1 14 1.00 1.00 14 1 9999 0.00300 Parafit
Jousselin_et_al_2009 2009 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Buchnera resident 55 22 1 22 1.00 1.00 22 1 9999 0.00100 Parafit
Kaltenpoth_et_al_2014 2014 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Beewolf bacterial symbiont resident 39 39 2 41 1.00 1.00 41 1 1000 0.00100 Parafit
Kawakita_&_Kato_2009 2009 Plant Plant Invert Invert y Mutualist Ecto horizontal autonomous Yucca moth visitor 10 10 7 10 1.00 1.00 10 1 100 0.39000 Parafit
Kawakita_et_al_2004 2004 Plant Plant Invert Invert y Mutualist Ecto horizontal autonomous Pollinating moth visitor 18 18 1 18 1.00 1.00 18 1 999 0.00500 Parafit
Kawazoe_et_al_2008 2008 Invert Invert Invert Invert y Mutualist Ecto vertical vertical Bee mite resident 4 4 1 5 1.25 1.25 4 1 9999 0.00010 Parafit
Kolsch_&__Pedersen_2010 2010 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Reed beetle bacterial endosymbiont resident 41 41 7 41 1.00 1.00 41 1 9999 0.00100 Parafit
Krasnov_&_Shenbrot_2013 2013 Vert Mammal Invert Invert y Parasite Ecto horizontal contact Jerboa fleas resident 21 21 8 62 3.26 4.37 19 7 999 0.16000 Parafit
Krumbholz_et_al_2009 2009 Vert Vert Microbe Virus n Parasite Endo horizontal NA Polyomavirus resident 13 13 13 18 1.00 1.00 18 1 999999 0.49460 Parafit
Ku_&_Hu_2014 2014 Plant Plant Microbe Bacterium n Mutualist Endo vertical vertical Burkholderia plant symbiont resident 11 11 1 11 1.00 1.00 11 1 9999 0.02000 Parafit
Lanterbecq_et_al_2010 2010 Invert Invert Invert Invert y Parasite Endo/Ecto horizontal contact Myzostomid worm resident 16 16 12 16 1.00 1.00 16 5 1000 0.01300 Parafit
Lauron_et_al_2015 2015 Vert Bird Microbe Protist y Parasite Endo horizontal vector Avian malaria resident 18 18 8 83 1.80 NA 46 1 1000 0.66000 Parafit
Lei_&_Olival_2014 2014 Vert Mammal Microbe Bacterium n Parasite Endo horizontal environmental New World bat Bartonella resident 14 14 11 38 1.00 1.00 38 1 999 0.00100 Parafit
Lei_&_Olival_2014 2014 Vert Mammal Microbe Bacterium n Parasite Endo horizontal environmental New World rodent Bartonella resident 4 4 4 20 1.00 1.00 20 1 999 0.00100 Parafit
Lei_&_Olival_2014 2014 Vert Mammal Microbe Bacterium n Parasite Endo horizontal environmental New World bat Leptospira resident 14 14 12 19 1.00 1.00 19 1 999 0.85800 Parafit
Lei_&_Olival_2014 2014 Vert Mammal Microbe Bacterium n Parasite Endo horizontal environmental Old World bat Bartonella resident 9 9 8 13 1.00 1.00 13 1 999 0.02900 Parafit
Lei_&_Olival_2014 2014 Vert Mammal Microbe Bacterium n Parasite Endo horizontal environmental Old World rodent Bartonella resident 35 35 22 119 1.09 1.17 109 1 999 0.00010 Parafit
Lei_&_Olival_2014 2014 Vert Mammal Microbe Bacterium n Parasite Endo horizontal environmental Old World bat Leptospira resident 6 6 5 7 1.00 1.00 7 1 999 0.75870 Parafit
LewisRogers_&_Crandall_2009 2009 Vert Tetrapod Microbe Virus n Parasite Endo horizontal contact Picornaviridae resident 6 6 NA 27 1.00 1.00 27 11 999 0.47000 Parafit
Li_et_al_2017 2017 Plant Plant Microbe Fungus y Parasite Endo horizontal autonomous Smut fungi resident 12 12 9 12 1.71 1.57 7 1 999 0.50505 Parafit
Light_&_Hafner_2008 2008 Vert Mammal Invert Invert y Parasite Ecto both contact Rodent sucking lice resident 44 21 4 21 1.00 1.00 21 1 999 0.00100 Parafit
Liu_et_al_2016 2016 Plant Plant Microbe Fungus y Parasite Endo NA environmental Tree foliar fungi resident 13 13 10 44 1.57 2.71 28 28 9999 0.02510 Parafit
Liu_et_al_2016 2016 Plant Plant Microbe Fungus y Parasite Endo NA environmental Subtropical tree soil fungi resident 19 19 16 76 3.30 3.22 23 23 9999 0.02030 Parafit
Maneesakorn_et_al_2011 2011 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Photorhabdus symbiotic bacteria in nematodes resident 12 12 1 12 1.00 1.00 12 1 999 0.00100 Parafit
Martinez_et_al_2011 2011 Invert Invert Microbe Protist y Parasite Endo horizontal vector Avian malaria resident 16 16 1 22 2.44 1.56 9 1 999 0.07500 Parafit
Martinez_San_udo_&_Girolami_2009 2009 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Tephritid symbiotic bacteria resident 19 19 10 19 1.12 1.18 17 5 999 0.00300 Parafit
Mattiucci_&_nascetti_2008 2008 Vert Mammal Invert Invert y Parasite Endo horizontal trophic Nematode resident 7 7 15 12 1.33 1.78 9 1 100 0.05000 Parafit
Mazzon_et_al_2010 2010 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Stammerula bacterial symbiont resident 17 17 10 17 1.06 1.00 16 3 999 0.00700 Parafit
McFrederick_&_Taylor_2013 2013 Invert Invert Invert Invert y NA Ecto vertical vertical Nematode resident 7 7 3 7 1.00 1.00 7 1 10000 0.00600 Parafit
McKee_et_al_2016 2016 Vert Mammal Microbe Bacterium n Parasite Endo horizontal vector Bat bartonella bacteria resident 66 66 42 184 1.06 1.09 173 1 10000 0.00010 Parafit
McLeish_&_Van_Noort_2012 2012 Plant Plant Invert Invert y Mutualist Endo horizontal autonomous Fig wasp resident 26 26 1 65 1.00 1.00 65 6 9999 0.18000 Parafit
Mehdiabadi_et_al_2012 2012 Invert Invert Microbe Fungus y Mutualist Ecto both environmental Ant fungus resident 99 11 1 11 1.00 1.00 11 1 999 0.00100 Parafit
Mendlova_et_al_2012 2012 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Monogenea resident 6 6 5 34 1.17 1.21 29 2 999 0.02400 Parafit
Merville_et_al._2013 2013 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Curculioniphilus buchneri primary endosymbiont of weevils resident 9 9 1 9 1.00 1.00 9 1 999 0.00350 Parafit
Millanes_et_al_2014 2014 Microbe Fungus Microbe Fungus y Parasite Endo both environmental Biatoropsis fungus resident 16 16 2 16 1.00 1.00 16 1 999 0.23600 Parafit
Miyaki_et_al_2016 2016 Vert Fish Microbe Bacterium n Mutualist Endo horizontal environmental Giant bacteria Epulopiscium resident 8 8 4 54 3.18 2.24 17 1 999 0.00100 Parafit
Mondo_et_al_2012 2012 Microbe Fungus Microbe Bacterium n Mutualist Endo vertical vertical Glomeribacter gigasporarum fungal symbiont resident 55 5 2 5 1.00 1.00 5 1 10000 0.00010 Parafit
Nouioui_et_al_2014 2014 Plant Plant Microbe Bacterium n Mutualist Endo horizontal vector Frankia resident 9 9 1 20 1.00 1.00 20 1 9999 0.33000 Parafit
Pellissier_et_al_2013 2013 Plant Plant Invert Invert y Parasite Ecto horizontal autonomous Butterflies visitor 104 104 NA NA NA NA 97 NA 10000 0.00010 Parafit
Perkins_2010 2010 Vert Fish Invert Invert y Parasite Endo horizontal autonomous Monogenea resident 61 61 50 75 1.00 1.00 75 NA 9999 0.92600 Parafit
Peterson_et_al_2010 2010 Plant Plant Microbe Fungus y Parasite Endo horizontal environmental Beech fungus resident 11 11 1 25 2.08 1.58 12 1 9999 0.00010 Parafit
Polme_et_al_2014.pdf 2014 Plant Plant Microbe Bacterium n Mutualist Endo horizontal vector Frankia resident 22 22 1 NA NA NA 43 1 999 0.00100 Parafit
Quek_et_al_2004 2004 Plant Plant Invert Invert y Mutualist Ecto horizontal autonomous Ant resident 10 10 1 23 2.30 1.70 10 1 999 0.77900 Parafit
Ricklefs_et_al_2004 2004 Vert Bird Microbe Protist y Parasite Endo horizontal vector Avian malaria resident 44 44 1 121 1.86 NA 65 2 100 0.63000 Parafit
Savio_2011 2011 Invert Invert Microbe Bacterium n Mutualist Endo horizontal NA Erwinia dacicola tephritid symbiont resident 17 17 10 17 1.00 1.00 17 3 999 0.00700 Parafit
Schardl_et_al_2008 2008 Plant Plant Microbe Fungus y Mutualist Endo both NA Grass endophytic fungi (epichloae) resident 25 25 16 25 0.96 1.00 26 2 1000 0.00100 Parafit
Sibbald_et_al_2017 2017 Microbe Amoeba Microbe Protist y Mutualist Endo horizontal environmental Paramoeba resident 7 7 1 7 1.00 1.00 7 1 9999 0.00010 Parafit
Simkova_et_al_2013 2013 Vert Fish Invert Invert y Parasite Ecto horizontal autonomous Monogenea resident 5 5 1 21 1.00 1.00 21 1 999 0.01300 Parafit
Singh_et_al_2016 2016 Microbe Fungus Plant Plant y Mutualist Endo horizontal environmental Trebouxia algae resident 23 23 1 28 1.40 1.20 20 1 9999 0.00020 Parafit
Sontowski_et_al_2015 2015 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Wolbachia resident 14 14 4 14 1.00 1.00 14 1 100000 0.00300 Parafit
Sorenson_et_al_2004 2004 Vert Bird Vert Bird y Parasite Ecto horizontal autonomous Brood parasitic finches resident 33 33 10 34 1.62 1.43 21 1 1000 0.00100 Parafit
Stireman_et_al_2010 2010 Plant Plant Invert Invert y Parasite Endo horizontal autonomous Gall midge resident 15 15 10 39 1.39 1.25 28 1 9999 0.00080 Parafit
Sudakaran_et_al_2015 2015 Invert Invert Microbe Bacterium n Mutualist Endo NA NA Gordonibacter resident 16 16 7 22 1.00 1.00 22 1 1000 0.97800 Parafit
Sudakaran_et_al_2015 2015 Invert Invert Microbe Bacterium n Mutualist Endo NA NA Coriobacterium glomerans resident 14 14 6 26 1.00 1.00 26 1 1000 0.97400 Parafit
Summers_&_Rouse_2014 2014 Invert Invert Invert Invert y Parasite Endo/Ecto horizontal autonomous Myzostomida resident 53 53 36 78 1.13 1.23 69 10 9999 0.00050 Parafit
Susoy_&_Herrmann_2014 2014 Invert Invert Invert Invert y Mutualist Ecto vertical vertical Nematode resident 35 35 7 37 1.42 1.31 26 1 9999 0.00010 Parafit
Swafford_&_Bond_2010 2010 Invert Invert Invert Invert y Parasite Ecto horizontal contact Millipede mite resident 7 7 1 7 1.00 1.00 7 1 9999 0.31900 Parafit
Sweet_et_al_2016 2016 Vert Bird Invert Invert y Parasite Ecto both contact Dove wing lice resident 52 52 25 57 1.33 1.21 43 1 100000 0.00001 Parafit
Sweet_et_al_2016 2016 Vert Bird Invert Invert y Parasite Ecto both contact Dove body lice resident 52 52 25 58 1.18 1.14 49 4 100000 0.00001 Parafit
Tao_et_al_2013 2013 Vert Tetrapod Microbe Virus n Parasite Endo horizontal NA Polyomavirus resident 7 7 7 10 1.00 1.00 10 1 99999 0.17592 Parafit
Toju_et_al_2013 2013 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Curculioniphilus resident 27 27 4 27 1.00 1.00 27 1 99999 0.00001 Parafit
Urban_&_Cryan_2012 2012 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Fulgoroidea associated Betaproteobacteria resident 30 30 29 30 1.00 1.00 30 1 1000 0.00100 Parafit
Urban_&_Cryan_2012 2012 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Fulgoroidea associated Sulcia resident 40 40 38 40 1.00 1.00 40 1 1000 0.00300 Parafit
Viale_et_al_2015 2015 Invert Invert Microbe Bacterium n Mutualist Endo vertical vertical Fruit fly Stammerula resident 23 23 1 23 1.00 1.00 23 1 9999 0.00100 Parafit
Won_et_al_2008 2008 Invert Invert Microbe Bacterium n Mutualist Endo horizontal contact Mussel thiotroph symbiont resident 15 15 5 15 1.00 1.00 15 1 100 0.37000 Parafit

A. authors: The authors of the study and the date (citation form).

B. year: Year of publication of the study.

C. host_tax_broad: Separation of the host group according to broader taxonomic units (e.g. vertebrate, invertebrate, microbe, plant).

D. host_tax_fine*: Separation of the host group according to narrower taxonomic units (e.g. fish, tetrapod, bird, invertebrate, protist, bacterium, plant, fungus).

E. symbiont_tax_broad: Separation of the symbiont group according to broader taxonomic units (e.g. vertebrate, invertebrate, microbe, plant).

F. symbiont_tax_fine*: Separation of the symbiont group according to narrower taxonomic units (e.g. invertebrate, protist, virus, bacterium, fungus, plant, bird).

G. symbiont_euk*: Whether the symbiont is eukaryotic (state =‘yes’), or prokaryotic (state=‘no’).

H. symbiosis: The type of symbiont (e.g. parasite or mutualist). For this we followed the definition used by the authors of the study.

I. endo_or_ecto: Whether the symbiont lives outside the host (i.e. is an ectosymbiont), or inside the host (i.e. is an endosymbiont).

J. mode_of_transmission_broad: Whether the symbiont is transmitted vertically, horizontally, or both. For this, we followed the route of transmission specified by the authors of the study

K. mode_of_transmission_fine*: A finer-scale description of the mode of transmission of the symbiont (e.g. contact, vector, bodily fluid, vertical, trophic).

L. symbiont*: Shorthand description of the type of symbiont.

M. Visiting_symbiont?* Whether the symbiont is resident on the host (resident), or makes visits to the host or hosts (visitor).

N. host_tips_linked: The number of individual host taxa included in the cophylogenetic analysis.

O. host_tips_linked_corrected The same measure as for column N, ‘host_tips_linked’, but reduced to only include one member of each host species. This is included because some authors include multiple individuals of the same host species. Without correction, this artificially increases the apparent number of host species included in the study.

P. host_genera: A count of the number of host genera included in the cophylogenetic analysis

Q. total_host_symbioint_links The total number of links between host and symbiont taxa recorded in a study. If all symbionts were strict specialists, this would equal the number of symbionts included in the study. However, because symbionts are often associated with more than one host, this value is often higher than the total number of symbionts included in the study.

R. host_range_link_ratio: An estimation of symbiont host specificity, calculated by dividing the total number of links between hosts and symbionts (i.e. ‘total_host_symbiont_links’, column Q), by the total number of symbionts included in the study (i.e. ‘symbiont_tips_linked’, column T).

S. host_range_taxonomic_breadth: An alternative estimation of symbiont host specificity, calculated by first summing the number of host taxonomic ranks linked to each symbiont (i.e. single host species = 1, multiple host species in the same genera = 2, multiple host genera = 3, multiple host familes = 4, multiple host orders = 5), and dividing by the total number of symbionts included in the study (i.e. ‘symbiont_tips_linked’, column T)

T. symbiont_tips_linked The number of individual symbiont taxa included in the cophylogenetic analysis.

U. symbiont_genera: A count of the number of symbiont genera included in the cophylogenetic analysis.

V. no_randomizations: The number of phylogenetic randomizations performed during the cophylogenetic analysis.

W. p_value: The p-value reported for the cophylogenetic analysis, representing the likelihood that host and symbtion phylogenies display cospeciation.

X. method: Whether TreeMap or Parafit was used to obtain co-divergence or a p value.

Table of sample sizes

We present the number of sample size for two sepreate methods: TreeMap and Parafit (and combined) for effect sizes, papers and different levels of categorical varaibles (factors).

# selecting out variables, which we used for our analysis
dat <- full_data %>% select(-host_tax_fine, -symbiont_tax_fine, -symbiont_euk, -mode_of_transmission_fine, -symbiont, -`Visiting_symbiont?`)

# making a table of sample sizes for different variables
dat %>% group_by(method) %>% 
  summarise(
    `Effect sizes` = n(),
    Papers = n_distinct(authors),
    `Vertebrate hosts` = sum(host_tax_broad == "Vert", na.rm = T), # na.rm is important when NA exists
    `Invertebrate hosts` = sum(host_tax_broad == "Invert", na.rm = T),
    `Plant hosts`  = sum(host_tax_broad == "Plant", na.rm = T),
    `Microbe hosts` = sum(host_tax_broad == "Microbe", na.rm = T),
    `Vertebrate symbionts` = sum(symbiont_tax_broad  == "Vert", na.rm = T),
    `Invertebrate symbionts` = sum(symbiont_tax_broad  == "Invert", na.rm = T),
    `Plant symbionts`  = sum(symbiont_tax_broad  == "Plant", na.rm = T),
    `Microbe symbionts` = sum(symbiont_tax_broad  == "Microbe", na.rm = T),
    `Parastic relationships` = sum(symbiosis == "Parasite", na.rm = T),
    `Mutualistic relatioships` = sum(symbiosis == "Mutualist", na.rm = T),
    `Ecto-symbionts` = sum(endo_or_ecto  == "Ecto", na.rm = T),
    `Endo-symbionts` = sum(endo_or_ecto == "Endo", na.rm = T),
    `Ecto/endo-symbionts` = sum(endo_or_ecto == "Endo/Ecto", na.rm = T),
    `Horizontal transmission` = sum(mode_of_transmission_broad  == "horizontal", na.rm = T),
    `Vertical transmission` = sum(mode_of_transmission_broad == "vertical", na.rm = T),
    `Horizontal/vertical-transmission` = sum(mode_of_transmission_broad == "both", na.rm = T)
  ) -> n_table1

# transposing the table and creating that table and adding a correct number of the papers for `Combined`
n_authors <- n_distinct(dat$authors) # the total number of papers
n_table2 <-t(n_table1[,-1])
colnames(n_table2) <- n_table1$method
n_table2 %>% as_tibble(rownames = "Number") %>% 
  mutate(Combined = Parafit + TreeMap, Combined = replace(Combined, 2, n_authors)) %>%  
  rename("Number of" = "Number", "Parafit (n)" = "Parafit", "TreeMap (n)" = "TreeMap",  "Combined (n)" = "Combined") %>% 
  kable() %>% kable_styling("striped", position = "left") %>%
  scroll_box(width = "100%", height = "250px")
Number of Parafit (n) TreeMap (n) Combined (n)
Effect sizes 140 93 233
Papers 118 78 180
Vertebrate hosts 60 51 111
Invertebrate hosts 39 20 59
Plant hosts 31 18 49
Microbe hosts 10 4 14
Vertebrate symbionts 1 1 2
Invertebrate symbionts 62 49 111
Plant symbionts 3 1 4
Microbe symbionts 74 42 116
Parastic relationships 91 70 161
Mutualistic relatioships 48 23 71
Ecto-symbionts 41 34 75
Endo-symbionts 97 58 155
Ecto/endo-symbionts 2 1 3
Horizontal transmission 84 53 137
Vertical transmission 28 15 43
Horizontal/vertical-transmission 23 25 48
  #pander(split.cell = 40, split.table = Inf) # not as nice as kable

Note that for the numbers of papers do not add up (TreeMap + Parafit \(\neq\) Combined) becuase 16 papers used both TreeMap and Parafit methods (the term “papers” here is our variable auhtors)

Missing data patterns

Here we have the number of missing data (cells) for all the varaibles used in the analysis below.

# summaring missingness in our dataset
# funs(sum(is.na(.))) needs to be in funs as is.na has "." = each column
dat %>% summarise_all(~sum(is.na(.))) %>% # map(~sum(is.na(.)) # this is an alterantive way 
  t() %>% as_tibble(rownames = "Variable") %>% 
  rename("Number of missing data (n)" = "V1") %>% 
  #pander(split.cell = 40, split.table = Inf)
  kable() %>% kable_styling("striped", position = "left") %>%
  scroll_box(width = "60%", height = "250px")
Variable Number of missing data (n)
authors 0
year 0
host_tax_broad 0
symbiont_tax_broad 0
symbiosis 1
endo_or_ecto 0
mode_of_transmission_broad 5
host_tips_linked 0
host_tips_linked_corrected 0
host_genera 6
total_host_symbioint_links 3
host_range_link_ratio 3
host_range_taxonomic_breadth 7
symbiont_tips_linked 0
symbiont_genera 9
no_randomizations 0
p_value 0
method 0
# an alternative method using the mi package
#missing_data_tbl <- missing_data.frame(as.data.frame(data))
#show(missing_data_tbl) 

Meta-analysis

Calculating effect sizes

Here, we creatde our effect size (correlation coefficent r and its Fisher’s z transformaiton Zr) from p values and associated sample sizes. We used the sum of host_tips_linked_corrected and symbiont_tips_linked as our sample size (i.e., the number of both host and symbiont species) for each effect size (an indicator of congruence). Also, we creat a column with unique ID for each observation (i.e. an observation level random effect), termed observation, which is required for the rma.mv function in metafor.

dat %<>% # getting sample size & observation level random effect
mutate(., sample_size = host_tips_linked_corrected + symbiont_tips_linked, observation = factor(1:nrow(.)))
# calcuating effect size somehow it did not run by piping with above (not
# recognising the first aurgument)
dat %<>% p_to_Zr(p_value, sample_size)

# TODO some factor reordering required!!!
levels = c("small", "medium", "large")

Meta-analytic model: testing Fahrenholz’s rule

First, we checked what random effects should be put into the main model to do this we fitted two random effects, authors and observation; the former term was added to account for non-independence of effect sizes orginating from the same papers (i.e., authors).

# 2 random effects & model AIC note that probably only base stuff works
# outside of main chunck so need to create AIC here
ma_test1 <- rma.mv(yi = Zr, V = VZr, random = list(~1 | authors, ~1 | observation), 
    data = dat)
aic1 <- AIC(ma_test1)

# 1 random effect & model AIC
ma_test2 <- rma.mv(yi = Zr, V = VZr, random = ~1 | authors, data = dat)
aic2 <- AIC(ma_test2)

The model (ma_test1), which included both random factors, had a larger AIC value (39.91) than the model with only one random effect (37.91) . This is becuase observation hardly accounted any variance (< 0.0001) compared to authors (0.0327). Therefore, we only had authors as our random factor in subsquentb analyses.

We ran intercept models (meta-analyses) with 3 different datasets (Parafit, TreeMap and both combined; see the explantion of method above). Also, we note that we used adjustments for test statistics and confidence intervals (test = "t"), which is similar to (but not the same as) those proposed by Kanpp and Hartung (2003); probably this approch is a more conservative approach.

Running Multilevel Meta-analytic models with 3 datasets

# think about making this into a tibble meta-analysis with Parafit
ma_parafit <- rma.mv(yi = Zr, V = VZr, random = ~1 | authors, test = "t", subset = which(method == 
    "TreeMap"), data = dat)

# meta-analysis with TreeMap
ma_treemap <- rma.mv(yi = Zr, V = VZr, random = ~1 | authors, test = "t", subset = which(method == 
    "Parafit"), data = dat)

# meta-analysis with all the data combined
ma_all <- rma.mv(yi = Zr, V = VZr, test = "t", random = ~1 | authors, data = dat)

Supplementary Table 1: Overall effects (meta-analytic means), 95% confidence intervals (CIs), variance components (V) and heterogeneity, I2 (I2) from metafor model using the 3 datasets (Parafit, TreeMap and both combined, or All). Note that in these models, I2[total] = I2[authors] (see Nakagawa & Santos 2012; REF - probably Senior as well?), as we only have one random factor.

# getting I2 for the models could use map()
i2_treemap <- I2(ma_treemap)
i2_parafit <- I2(ma_parafit)
i2_all <- I2(ma_all)
# creating a table
tibble(Dataset = c("Parafit", "TreeMap", "All"), `Overall mean (Zr)` = c(ma_parafit$b, 
    ma_treemap$b, ma_all$b), `Lower CI [0.025]` = c(ma_parafit$ci.lb, ma_treemap$ci.lb, 
    ma_all$ci.lb), `Upper C  [0.975]` = c(ma_parafit$ci.ub, ma_treemap$ci.ub, 
    ma_all$ci.ub), `V[authors]` = c(ma_parafit$sigma2, ma_treemap$sigma2, ma_all$sigma2), 
    `I2[total]` = c(i2_parafit[1], i2_treemap[1], i2_all[1])) %>% kable("html", 
    digits = 3) %>% kable_styling("striped", position = "left")
Dataset Overall mean (Zr) Lower CI [0.025] Upper C [0.975] V[authors] I2[total]
Parafit 0.333 0.273 0.394 0.036 0.523
TreeMap 0.350 0.308 0.392 0.028 0.600
All 0.345 0.309 0.381 0.033 0.590

These models gave all consistant results including heterogeneity. Given these results, we proceeded with only analysing the whole dataset (All) from this on.

# creating a table of results
pred_ma <- get_pred(ma_all)
effect_ma <- get_est(ma_all) %>% left_join(pred_ma)

# creating a forest plot
fig_ma <- ggplot(data = effect_ma, aes(x = tanh(estimate), y = "Overall mean")) + 
    scale_x_continuous(limits = c(-1, 1), breaks = seq(-1, 1, by = 0.2)) + geom_quasirandom(data = dat, 
    aes(x = tanh(Zr), y = "Overall mean", size = (1/VZr) + 3), groupOnX = FALSE, 
    alpha = 0.2) + # precition interval (PI)
geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)), height = 0, 
    show.legend = F, size = 0.5, alpha = 0.6) + # CI
geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)), height = 0, 
    show.legend = F, size = 1.2) + 
geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) + # creating dots and different size (bee-swarm and bubbles)
geom_point(size = 3, shape = 21, fill = "black") + annotate("text", x = -1, 
    y = "Overall mean", label = paste("italic(k)==", length(dat$Zr)), parse = TRUE, 
    hjust = "left", size = 3.5) + labs(x = expression(paste(italic(r), " (correlaton)")), 
    y = "", size = expression(paste(italic(n), " (# of species)"))) + theme_bw() + 
    theme(legend.position = c(0, 1), legend.justification = c(0, 1)) + theme(legend.direction = "horizontal") + 
    # theme(legend.background = element_rect(fill = 'white', colour = 'black'))
# +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90))

# ggsave(plot = fig_ma, filename = 'fig_2a.pdf', height = 2, width = 8)
# ggploty 0 does not work (Error in unique.default(x) : unimplemented type
# 'expression' in 'HashTableSetup')
fig_ma

Figure 2a: The effect XXXXXX

Meta-regression

We ran a univaraite meta-regression model for each of following moderators: 1) symbiosis, 2) host_tax_broad, 3) symbiont_tax_broad, 4) host_range_link_ratio, 5) host_range_taxonomic_breadth, 6) mode_of_transmission_broad, and 7) endo_or_ecto. The results from these models are presented in the main text.

In addtion to these, we ran three more univariate models: 1) host_tax_symbiosis (equivalent to the interactoin term between symbiosis and host_tax_symbiosis; symbiosis*host_tax_symbiosis), 2) symbiont_tax_symbiosis (symbiosis*symbiont_tax_broad), 3) host_symbiont_tax (host_tax_symbiosis*symbiont_tax_broad) and 4) symbiosis_transmission (symbiosis*mode_of_transmission_broad). There moderators are created below:

dat %<>% 
    # host_tax_broad*symbiosis (host_tax_symbiosis) 
  mutate(host_tax_symbiosis = str_c(host_tax_broad, symbiosis), 
         host_tax_symbiosis = ifelse(host_tax_symbiosis == "InvertNA", NA, host_tax_symbiosis),
         host_tax_symbiosis = factor(host_tax_symbiosis),
         # symbiont_tax_broad*symbiosis (symbiont_tax_symbiosis)     
         symbiont_tax_symbiosis = factor(str_c(symbiont_tax_broad, symbiosis)),
         # host_tax_broad*symbiont_tax_broad (host_symbiont_tax)     
         host_symbiont_tax  = factor(str_c(host_tax_broad, symbiont_tax_broad)),
         # symbiosis*mode_of_transmission_broad (symbiosis_transmission)
         symbiosis_transmission  = factor(str_c(symbiosis, mode_of_transmission_broad)),
         # whether p values were the smallest value given the number of randamization - limit_researched (Yes = 1, No = 0)
         limit_rearched = if_else(abs((1/p_value) - no_randomizations) <= 1, 1, 0))

Univaraite (Uni-predictor) analyses

The type of symbiosis: parasitism vs. mutualism

# meta-regression: mutiple intercepts
mr_symbiosis1 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiosis - 1, test = "t", 
    random = ~1 | authors, data = dat)
# meta-regression: contrast
mr_symbiosis2 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiosis, test = "t", random = ~1 | 
    authors, data = dat)

Supplementary Table 2: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiosis.

# getting marginal R2
r2_symbiosis1 <- R2(mr_symbiosis1)

# getting estimates
res_symbiosis1 <- get_est(mr_symbiosis1, mod = "symbiosis")
res_symbiosis2 <- get_est(mr_symbiosis2, mod = "symbiosis")

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiosis1$name), cont_gen(res_symbiosis1$name)), 
    Estimate = c(res_symbiosis1$estimate, res_symbiosis2$estimate[2]), `Lower CI [0.025]` = c(res_symbiosis1$lowerCL, 
        res_symbiosis2$lowerCL[2]), `Upper CI  [0.975]` = c(res_symbiosis1$upperCL, 
        res_symbiosis2$upperCL[2]), `V[authors]` = c(mr_symbiosis1$sigma2, rep(NA, 
        2)), R2 = c(r2_symbiosis1[1], rep(NA, 2))) %>% kable("html", digits = 3) %>% 
    kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Mutualist 0.411 0.349 0.473 0.031 0.064
Parasite 0.311 0.268 0.354 NA NA
Mutualist-Parasite -0.100 -0.174 -0.026 NA NA
# adding sample size (k) for each category
k_symbiosis <- dat %>% group_by(symbiosis) %>% count()
# getting estimates and predicitons
pred_symbiosis <- get_pred(mr_symbiosis1, mod = "symbiosis") 
res_symbiosis1 <- left_join(res_symbiosis1, k_symbiosis, by =  c("name" = "symbiosis"))  %>% left_join(pred_symbiosis)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_symbiosis <- ggplot(data = res_symbiosis1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiosis)), 
                   aes(x= tanh(Zr), y = symbiosis, size = ((1/VZr) + 3), colour = symbiosis), groupOnX = FALSE, alpha=0.2) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Mutualist" = "#E69F00", "Parasite" = "#56B4E9")) +
  scale_fill_manual(values = c("Mutualist" = "#E69F00", "Parasite" = "#56B4E9")) +
  annotate('text', x = -1, y = res_symbiosis1$name, label= paste("italic(k)==", res_symbiosis1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_symbiosis

Figure 2b: The effect XXXXXX

The effect of host taxa

# reordering
dat$host_tax_broad <- factor(dat$host_tax_broad, levels = c("Microbe", "Plant", 
    "Invert", "Vert"))

# meta-regression: mutiple intercepts
mr_host_tax_broad1 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_broad - 1, test = "t", 
    random = ~1 | authors, data = dat)

# meta-regression: contrast 1
mr_host_tax_broad2 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_broad, test = "t", 
    random = ~1 | authors, data = dat)

# meta-regression: contrast 2
mr_host_tax_broad3 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(host_tax_broad, 
    ref = "Plant"), test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 3
mr_host_tax_broad4 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(host_tax_broad, 
    ref = "Invert"), test = "t", random = ~1 | authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with host_tax_broad.

# getting marginal R2
r2_host_tax_broad1 <- R2(mr_host_tax_broad1)

# getting estimates
res_host_tax_broad1 <- get_est(mr_host_tax_broad1, mod = "host_tax_broad")
res_host_tax_broad2 <- get_est(mr_host_tax_broad2, mod = "host_tax_broad")
# the name bit does not work if relevel....
res_host_tax_broad3 <- get_est(mr_host_tax_broad3, mod = "host_tax_broad")
res_host_tax_broad4 <- get_est(mr_host_tax_broad4, mod = "host_tax_broad")

# creating a table
tibble(`Fixed effect` = c(as.character(res_host_tax_broad1$name), cont_gen(res_host_tax_broad1$name)), 
    Estimate = c(res_host_tax_broad1$estimate, res_host_tax_broad2$estimate[-1], 
        res_host_tax_broad3$estimate[-(1:2)], res_host_tax_broad4$estimate[-(1:3)]), 
    `Lower CI [0.025]` = c(res_host_tax_broad1$lowerCL, res_host_tax_broad2$lowerCL[-1], 
        res_host_tax_broad3$lowerCL[-(1:2)], res_host_tax_broad4$lowerCL[-(1:3)]), 
    `Upper CI  [0.975]` = c(res_host_tax_broad1$upperCL, res_host_tax_broad2$upperCL[-1], 
        res_host_tax_broad3$upperCL[-(1:2)], res_host_tax_broad4$upperCL[-(1:3)]), 
    `V[authors]` = c(mr_host_tax_broad1$sigma2, rep(NA, 9)), R2 = c(r2_host_tax_broad1[1], 
        rep(NA, 9))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left") %>% scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Microbe 0.557 0.404 0.710 0.03 0.168
Plant 0.244 0.168 0.321 NA NA
Invert 0.412 0.344 0.480 NA NA
Vert 0.327 0.277 0.378 NA NA
Microbe-Plant -0.312 -0.483 -0.141 NA NA
Microbe-Invert -0.144 -0.312 0.023 NA NA
Microbe-Vert -0.229 -0.390 -0.068 NA NA
Plant-Invert 0.168 0.065 0.270 NA NA
Plant-Vert 0.083 -0.009 0.175 NA NA
Invert-Vert -0.085 -0.168 -0.002 NA NA
# adding sample size (k) for each category
k_host_tax_broad <- dat %>% group_by(host_tax_broad) %>% count()
# getting estimates and predicitons
pred_host_tax_broad <- get_pred(mr_host_tax_broad1, mod = "host_tax_broad") 
res_host_tax_broad1 <- left_join(res_host_tax_broad1, k_host_tax_broad, by =  c("name" = "host_tax_broad"))  %>% left_join(pred_host_tax_broad)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_host_tax_broad <- ggplot(data = res_host_tax_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(host_tax_broad)), 
                   aes(x= tanh(Zr), y = host_tax_broad, size = ((1/VZr) + 3), colour = host_tax_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_fill_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_y_discrete(labels = c("Microbe" = "Microbe",  "Plant" = "Plant",  "Invert"= "Invertebrate",  "Vert" = "Vertebrate")) +
  annotate('text', x = -1, y = res_host_tax_broad1$name, label= paste("italic(k)==", res_host_tax_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_host_tax_broad

Figure 2c: The effect XXXXXX

The effect of symbiont taxa

# reordering
dat$symbiont_tax_broad <- factor(dat$symbiont_tax_broad, levels = c("Microbe", 
    "Plant", "Invert", "Vert"))

# sizes <- factor(sizes, levels = c('small', 'medium', 'large')) sizes > [1]
# small large large small medium > Levels: small medium large
# meta-regression: mutiple intercepts
mr_symbiont_tax_broad1 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiont_tax_broad - 
    1, test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 1
mr_symbiont_tax_broad2 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiont_tax_broad, 
    test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 2
mr_symbiont_tax_broad3 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(symbiont_tax_broad, 
    ref = "Plant"), test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 3
mr_symbiont_tax_broad4 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(symbiont_tax_broad, 
    ref = "Invert"), test = "t", random = ~1 | authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_symbiont_tax_broad1 <- R2(mr_symbiont_tax_broad1)

# getting estimates
res_symbiont_tax_broad1 <- get_est(mr_symbiont_tax_broad1, mod = "symbiont_tax_broad")
res_symbiont_tax_broad2 <- get_est(mr_symbiont_tax_broad2, mod = "symbiont_tax_broad")
res_symbiont_tax_broad3 <- get_est(mr_symbiont_tax_broad3, mod = "symbiont_tax_broad")
res_symbiont_tax_broad4 <- get_est(mr_symbiont_tax_broad4, mod = "symbiont_tax_broad")

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiont_tax_broad1$name), cont_gen(res_symbiont_tax_broad1$name)), 
    Estimate = c(res_symbiont_tax_broad1$estimate, res_symbiont_tax_broad2$estimate[-1], 
        res_symbiont_tax_broad3$estimate[-(1:2)], res_symbiont_tax_broad4$estimate[-(1:3)]), 
    `Lower CI [0.025]` = c(res_symbiont_tax_broad1$lowerCL, res_symbiont_tax_broad2$lowerCL[-1], 
        res_symbiont_tax_broad3$lowerCL[-(1:2)], res_symbiont_tax_broad4$lowerCL[-(1:3)]), 
    `Upper CI  [0.975]` = c(res_symbiont_tax_broad1$upperCL, res_symbiont_tax_broad2$upperCL[-1], 
        res_symbiont_tax_broad3$upperCL[-(1:2)], res_symbiont_tax_broad4$upperCL[-(1:3)]), 
    `V[authors]` = c(mr_symbiont_tax_broad1$sigma2, rep(NA, 9)), R2 = c(r2_symbiont_tax_broad1[1], 
        rep(NA, 9))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left") %>% scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Microbe 0.353 0.303 0.403 0.032 0.082
Plant 0.733 0.440 1.027 NA NA
Invert 0.324 0.270 0.377 NA NA
Vert 0.291 -0.112 0.694 NA NA
Microbe-Plant 0.380 0.083 0.678 NA NA
Microbe-Invert -0.029 -0.102 0.044 NA NA
Microbe-Vert -0.062 -0.468 0.345 NA NA
Plant-Invert -0.410 -0.708 -0.111 NA NA
Plant-Vert -0.442 -0.941 0.057 NA NA
Invert-Vert -0.033 -0.440 0.374 NA NA
# adding sample size (k) for each category
k_symbiont_tax_broad <- dat %>% group_by(symbiont_tax_broad) %>% count()
# getting estimates and predicitons
pred_symbiont_tax_broad <- get_pred(mr_symbiont_tax_broad1, mod = "symbiont_tax_broad") 
res_symbiont_tax_broad1 <- left_join(res_symbiont_tax_broad1, k_symbiont_tax_broad, by =  c("name" = "symbiont_tax_broad"))  %>% left_join(pred_symbiont_tax_broad)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_symbiont_tax_broad <- ggplot(data = res_symbiont_tax_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiont_tax_broad)), 
                   aes(x= tanh(Zr), y = symbiont_tax_broad, size = ((1/VZr) + 3), colour = symbiont_tax_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00" )) +
  scale_fill_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_y_discrete(labels = c("Microbe" = "Microbe",  "Plant" = "Plant",  "Invert"= "Invertebrate",  "Vert" = "Vertebrate")) +
  annotate('text', x = -1, y = res_symbiont_tax_broad1$name, label= paste("italic(k)==", res_symbiont_tax_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_symbiont_tax_broad

Figure 2d: The effect XXXXXX

Testing specialization 1: host range

# meta-regression
mr_host_range_link_ratio <- rma.mv(yi = Zr, V = VZr, mods = ~log(host_range_link_ratio), 
    random = ~1 | authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_host_range_link_ratio <- R2(mr_host_range_link_ratio)

# getting estimates: name does not work for slopes
res_host_range_link_ratio <- get_est(mr_host_range_link_ratio, mod = "log(host_range_link_ratio)")

# creating a table
tibble(`Fixed effect` = c("Intercept", "log(host_range_link_ratio)"), Estimate = c(res_host_range_link_ratio$estimate), 
    `Lower CI [0.025]` = c(res_host_range_link_ratio$lowerCL), `Upper CI  [0.975]` = c(res_host_range_link_ratio$upperCL), 
    `V[authors]` = c(mr_host_range_link_ratio$sigma2, NA), R2 = c(r2_host_range_link_ratio[1], 
        NA)) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept 0.360 0.318 0.401 0.033 0.012
log(host_range_link_ratio) -0.057 -0.150 0.037 NA NA
# newmods <- seq(-0.3, 2.2, by = 0.1)
# pred_host_range_link_ratio <-predict.rma(mr_host_range_link_ratio, newmods = newmods) 
# ribbon_dat <- tibble(newmods = newmods, ymin = pred_host_range_link_ratio$ci.lb, ymax = pred_host_range_link_ratio$ci.ub)
pred_host_range_link_ratio <-predict.rma(mr_host_range_link_ratio) 

# plotting

fig_host_range_link_ratio <-  dat %>% 
  filter(!is.na(host_range_link_ratio))  %>% # getting ride of NA values
  mutate(ymin = pred_host_range_link_ratio$ci.lb, 
         ymax = pred_host_range_link_ratio$ci.ub,
         ymin2 = pred_host_range_link_ratio$cr.lb,
         ymax2 = pred_host_range_link_ratio$cr.ub,
         pred = pred_host_range_link_ratio$pred) %>% 
  ggplot(aes(x = log(host_range_link_ratio), y = Zr, size = (1/VZr) + 3, )) +
  geom_point(shape = 21, fill = "grey90") +
  #geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = "#0072B2")  + # not quite sure why this does not work
  geom_smooth(aes(y = ymin2), method =  "loess", se = FALSE, lty =  "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymax2), method =  "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymin), method =  "loess", se = FALSE,lty = "dotted", lwd = 0.25, colour ="#D55E00") +
  geom_smooth(aes(y = ymax), method =  "loess", se = FALSE, lty ="dotted", lwd = 0.25, colour ="#D55E00") + 
  geom_smooth(aes(y = pred), method =  "loess", se = FALSE, lty ="dashed", lwd = 0.5, colour ="black") +  
  ylim(-1, 2) + xlim(-0.05, 2) +
  #geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope = mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = "dashed", size = 0.5) +
  labs(x = "ln(range link ratio)", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), " (# of species)"))) +
  guides(fill = "none", colour = "none") +
  # themses
  theme_bw() +
  theme(legend.position= c(1, 1), legend.justification = c(1, 1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_host_range_link_ratio

Supplementary Figure 1:

Testing specialization 2: taxomic breadth

# meta-regression
mr_host_range_taxonomic_breadth <- rma.mv(yi = Zr, V = VZr, mods = ~log(host_range_taxonomic_breadth), 
    random = ~1 | authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_host_range_taxonomic_breadth <- R2(mr_host_range_taxonomic_breadth)

# getting estimates: name does not work for slopes
res_host_range_taxonomic_breadth <- get_est(mr_host_range_link_ratio, mod = "log(host_range_link_ratio)")

# creating a table
tibble(`Fixed effect` = c("Intercept", "log(host_range_taxonomic_breadth)"), 
    Estimate = c(res_host_range_taxonomic_breadth$estimate), `Lower CI [0.025]` = c(res_host_range_taxonomic_breadth$lowerCL), 
    `Upper CI  [0.975]` = c(res_host_range_taxonomic_breadth$upperCL), `V[authors]` = c(mr_host_range_taxonomic_breadth$sigma2, 
        NA), R2 = c(r2_host_range_taxonomic_breadth[1], NA)) %>% kable("html", 
    digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept 0.360 0.318 0.401 0.032 0.008
log(host_range_taxonomic_breadth) -0.057 -0.150 0.037 NA NA
pred_host_range_taxonomic_breadth <-predict.rma(mr_host_range_taxonomic_breadth) 

# plotting

fig_host_range_taxonomic_breadth <-  dat %>% 
  filter(!is.na(host_range_taxonomic_breadth))  %>% # getting ride of NA values
  mutate(ymin = pred_host_range_taxonomic_breadth$ci.lb, 
         ymax = pred_host_range_taxonomic_breadth$ci.ub,
         ymin2 = pred_host_range_taxonomic_breadth$cr.lb,
         ymax2 = pred_host_range_taxonomic_breadth$cr.ub,
         pred = pred_host_range_taxonomic_breadth$pred) %>% 
  ggplot(aes(x = log(host_range_taxonomic_breadth), y = Zr, size = (1/VZr) + 3, )) +
  geom_point(shape = 21, fill = "grey90") +
  #geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = "#0072B2")  + # not quite sure why this does not work
  geom_smooth(aes(y = ymin2), method =  "loess", se = FALSE, lty =  "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymax2), method =  "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymin), method =  "loess", se = FALSE,lty = "dotted", lwd = 0.25, colour ="#D55E00") +
  geom_smooth(aes(y = ymax), method =  "loess", se = FALSE, lty ="dotted", lwd = 0.25, colour ="#D55E00") + 
  geom_smooth(aes(y = pred), method =  "loess", se = FALSE, lty ="dashed", lwd = 0.5, colour ="black") +  
  ylim(-1, 2) + xlim(0, 1.5) +
  #geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope = mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = "dashed", size = 0.5) +
  labs(x = "ln(range link ratio)", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), " (# of species)"))) +
  guides(fill = "none", colour = "none") +
  # themses
  theme_bw() +
  theme(legend.position= c(1, 1), legend.justification = c(1, 1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_host_range_taxonomic_breadth

Supplementary Figure 2:

# reordering
dat$endo_or_ecto <- factor(dat$endo_or_ecto, levels = c("Endo/Ecto", "Endo", 
    "Ecto"))

# meta-regression: mutiple intercepts
mr_endo_or_ecto1 <- rma.mv(yi = Zr, V = VZr, mods = ~endo_or_ecto - 1, test = "t", 
    random = ~1 | authors, data = dat)

# meta-regression: contrast 1
mr_endo_or_ecto2 <- rma.mv(yi = Zr, V = VZr, mods = ~endo_or_ecto, test = "t", 
    random = ~1 | authors, data = dat)

# meta-regression: contrast 2
mr_endo_or_ecto3 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(endo_or_ecto, ref = "Endo"), 
    test = "t", random = ~1 | authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with endo_or_ecto.

# getting marginal R2
r2_endo_or_ecto1 <- R2(mr_endo_or_ecto1)

# getting estimates
res_endo_or_ecto1 <- get_est(mr_endo_or_ecto1, mod = "endo_or_ecto")
res_endo_or_ecto2 <- get_est(mr_endo_or_ecto2, mod = "endo_or_ecto")
res_endo_or_ecto3 <- get_est(mr_endo_or_ecto3, mod = "endo_or_ecto")

# creating a table
tibble(`Fixed effect` = c(as.character(res_endo_or_ecto1$name), cont_gen(res_endo_or_ecto1$name)), 
    Estimate = c(res_endo_or_ecto1$estimate, res_endo_or_ecto2$estimate[-1], 
        res_endo_or_ecto3$estimate[-(1:2)]), `Lower CI [0.025]` = c(res_endo_or_ecto1$lowerCL, 
        res_endo_or_ecto2$lowerCL[-1], res_endo_or_ecto3$lowerCL[-(1:2)]), `Upper CI  [0.975]` = c(res_endo_or_ecto1$upperCL, 
        res_endo_or_ecto2$upperCL[-1], res_endo_or_ecto3$upperCL[-(1:2)]), `V[authors]` = c(mr_endo_or_ecto1$sigma2, 
        rep(NA, 5)), R2 = c(r2_endo_or_ecto1[1], rep(NA, 5))) %>% kable("html", 
    digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Endo/Ecto 0.334 0.035 0.632 0.034 0.001
Endo 0.342 0.298 0.387 NA NA
Ecto 0.353 0.287 0.418 NA NA
Endo/Ecto-Endo 0.009 -0.293 0.311 NA NA
Endo/Ecto-Ecto 0.019 -0.287 0.325 NA NA
Endo-Ecto 0.010 -0.069 0.090 NA NA
# adding sample size (k) for each category
k_endo_or_ecto <- dat %>% group_by(endo_or_ecto) %>% count()
# getting estimates and predicitons
pred_endo_or_ecto <- get_pred(mr_endo_or_ecto1, mod = "endo_or_ecto") 
res_endo_or_ecto1 <- left_join(res_endo_or_ecto1, k_endo_or_ecto, by =  c("name" = "endo_or_ecto"))  %>% left_join(pred_endo_or_ecto)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_endo_or_ecto <- ggplot(data = res_endo_or_ecto1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(endo_or_ecto)), 
                   aes(x= tanh(Zr), y = endo_or_ecto, size = ((1/VZr) + 3), colour = endo_or_ecto), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Endo/Ecto" = "#0072B2",  "Endo" = "#D55E00",  "Ecto"= "#CC79A7")) +
  scale_fill_manual(values = c("Endo/Ecto" = "#0072B2",  "Endo" = "#D55E00",  "Ecto"= "#CC79A7")) +
  scale_y_discrete(labels = c("Endo/Ecto" = "Both",  "Endo" = "Endosymbiosis",  "Ecto"= "Ectosymbiosis")) +
  annotate('text', x = -1, y = res_endo_or_ecto1$name, label= paste("italic(k)==", res_endo_or_ecto1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction = "horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_endo_or_ecto

Figure 2g: The effect XXXXXX

The effect of the model of transmission

# meta-regression: mutiple intercepts
mr_mode_of_transmission_broad1 <- rma.mv(yi = Zr, V = VZr, mods = ~mode_of_transmission_broad - 
    1, test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 1
mr_mode_of_transmission_broad2 <- rma.mv(yi = Zr, V = VZr, mods = ~mode_of_transmission_broad, 
    test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 2
mr_mode_of_transmission_broad3 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(mode_of_transmission_broad, 
    ref = "vertical"), test = "t", random = ~1 | authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with mode_of_transmission_broad.

# getting marginal R2
r2_mode_of_transmission_broad1 <- R2(mr_mode_of_transmission_broad1)

# getting estimates
res_mode_of_transmission_broad1 <- get_est(mr_mode_of_transmission_broad1, mod = "mode_of_transmission_broad")
res_mode_of_transmission_broad2 <- get_est(mr_mode_of_transmission_broad2, mod = "mode_of_transmission_broad")
res_mode_of_transmission_broad3 <- get_est(mr_mode_of_transmission_broad3, mod = "mode_of_transmission_broad")

# creating a table
tibble(`Fixed effect` = c(as.character(res_mode_of_transmission_broad1$name), 
    cont_gen(res_mode_of_transmission_broad1$name)), Estimate = c(res_mode_of_transmission_broad1$estimate, 
    res_mode_of_transmission_broad2$estimate[-1], res_mode_of_transmission_broad3$estimate[-(1:2)]), 
    `Lower CI [0.025]` = c(res_mode_of_transmission_broad1$lowerCL, res_mode_of_transmission_broad2$lowerCL[-1], 
        res_mode_of_transmission_broad3$lowerCL[-(1:2)]), `Upper CI  [0.975]` = c(res_mode_of_transmission_broad1$upperCL, 
        res_mode_of_transmission_broad2$upperCL[-1], res_mode_of_transmission_broad3$upperCL[-(1:2)]), 
    `V[authors]` = c(mr_mode_of_transmission_broad1$sigma2, rep(NA, 5)), R2 = c(r2_mode_of_transmission_broad1[1], 
        rep(NA, 5))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
both 0.371 0.298 0.443 0.024 0.219
horizontal 0.285 0.242 0.328 NA NA
vertical 0.496 0.421 0.570 NA NA
both-horizontal -0.085 -0.170 -0.001 NA NA
both-vertical 0.125 0.021 0.229 NA NA
horizontal-vertical -0.210 -0.297 -0.124 NA NA
# adding sample size (k) for each category
k_mode_of_transmission_broad <- dat %>% group_by(mode_of_transmission_broad) %>% count()
# getting estimates and predicitons
pred_mode_of_transmission_broad <- get_pred(mr_mode_of_transmission_broad1, mod = "mode_of_transmission_broad") 
res_mode_of_transmission_broad1 <- left_join(res_mode_of_transmission_broad1, k_mode_of_transmission_broad, by =  c("name" = "mode_of_transmission_broad"))  %>% left_join(pred_mode_of_transmission_broad)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_mode_of_transmission_broad <- ggplot(data = res_mode_of_transmission_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(mode_of_transmission_broad)), 
                   aes(x= tanh(Zr), y = mode_of_transmission_broad, size = ((1/VZr) + 3), colour = mode_of_transmission_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("both" = "#0072B2",  "horizontal" = "#D55E00",  "vertical"= "#CC79A7")) +
  scale_fill_manual(values = c("both" = "#0072B2",  "horizontal" = "#D55E00",  "vertical"= "#CC79A7")) +
  scale_y_discrete(labels = c("both" = "Both",  "horizontal" = "Horizontal",  "vertical"= "Vertical")) +
  annotate('text', x = -1, y = res_mode_of_transmission_broad1$name, label= paste("italic(k)==", res_mode_of_transmission_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction = "horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_mode_of_transmission_broad

Figure 2g: The effect XXXXXX

The combined effect of symbiosis and mode of transmission

# reordering
dat$symbiosis_transmission <- factor(dat$symbiosis_transmission, levels = c("Mutualistboth", 
    "Mutualisthorizontal", "Mutualistvertical", "Parasiteboth", "Parasitehorizontal"), 
    labels = c("MutualistBoth", "MutualistHorizontal", "MutualistVertical", 
        "ParasiteBoth", "ParasiteHorizontal"))

# meta-regression: mutiple intercepts
mr_symbiosis_transmission1 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiosis_transmission - 
    1, test = "t", random = ~1 | authors, data = dat)

# # meta-regression: contrasts x 10 getting the level names out
level_names <- levels(dat$symbiosis_transmission)

# helper function to run metafor meta-regression
run_rma <- function(name) {
    rma.mv(yi = Zr, V = VZr, mods = ~relevel(symbiosis_transmission, ref = name), 
        test = "t", random = ~1 | authors, data = dat)
}

# results of meta-regression including all contrast results; taking the last
# level out ([-length(level_names)])
mr_symbiosis_transmission <- map(level_names[-length(level_names)], run_rma)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with host_tax_broad.

# getting marginal R2
r2_symbiosis_transmission1 <- R2(mr_symbiosis_transmission1)

# getting estimates
res_symbiosis_transmission1 <- get_est(mr_symbiosis_transmission1, mod = "symbiosis_transmission")
res_symbiosis_transmission <- map(mr_symbiosis_transmission, ~get_est(.x, mod = "symbiosis_transmission"))

# a list of the numbers to take out unnecessary contrasts
contra_list <- Map(seq, from = 1, to = 1:4)

# you need to flatten twice: first to make it a list and make it a vector
estiamtes <- map2(res_symbiosis_transmission, contra_list, ~.x[-(.y), "estimate"]) %>% 
    flatten() %>% flatten_dbl()
lowerCLs <- map2(res_symbiosis_transmission, contra_list, ~.x[-(.y), "lowerCL"]) %>% 
    flatten() %>% flatten_dbl()
upperCLs <- map2(res_symbiosis_transmission, contra_list, ~.x[-(.y), "upperCL"]) %>% 
    flatten() %>% flatten_dbl()

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiosis_transmission1$name), cont_gen(res_symbiosis_transmission1$name)), 
    Estimate = c(res_symbiosis_transmission1$estimate, estiamtes), `Lower CI [0.025]` = c(res_symbiosis_transmission1$lowerCL, 
        lowerCLs), `Upper CI  [0.975]` = c(res_symbiosis_transmission1$upperCL, 
        lowerCLs), `V[authors]` = c(mr_symbiosis_transmission1$sigma2, rep(NA, 
        (5 + choose(5, 2)) - 1)), R2 = c(r2_symbiosis_transmission1[1], rep(NA, 
        (5 + choose(5, 2)) - 1))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left") %>% scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
MutualistBoth 0.453 0.224 0.682 0.024 0.213
MutualistHorizontal 0.290 0.189 0.391 NA NA
MutualistVertical 0.493 0.417 0.568 NA NA
ParasiteBoth 0.362 0.285 0.439 NA NA
ParasiteHorizontal 0.284 0.238 0.331 NA NA
MutualistBoth-MutualistHorizontal -0.163 -0.413 -0.413 NA NA
MutualistBoth-MutualistVertical 0.040 -0.201 -0.201 NA NA
MutualistBoth-ParasiteBoth -0.091 -0.333 -0.333 NA NA
MutualistBoth-ParasiteHorizontal -0.168 -0.402 -0.402 NA NA
MutualistHorizontal-MutualistVertical 0.202 0.076 0.076 NA NA
MutualistHorizontal-ParasiteBoth 0.071 -0.056 -0.056 NA NA
MutualistHorizontal-ParasiteHorizontal -0.006 -0.115 -0.115 NA NA
MutualistVertical-ParasiteBoth -0.131 -0.239 -0.239 NA NA
MutualistVertical-ParasiteHorizontal -0.208 -0.297 -0.297 NA NA
ParasiteBoth-ParasiteHorizontal -0.077 -0.167 -0.167 NA NA
# colour list
colour_ls <- c("#000000", "#E69F00", "#56B4E9", "#009E73",  "#F0E422",  "#0072B2",  "#D55E00", "#CC79A7", "#00008B", "#8B0A50", "#54FF9F", "#999999")

# adding sample size (k) for each category
k_symbiosis_transmission <- dat %>% group_by(symbiosis_transmission) %>% count()
# getting estimates and predicitons
pred_symbiosis_transmission <- get_pred(mr_symbiosis_transmission1, mod = "symbiosis_transmission") 
res_symbiosis_transmission1 <- left_join(res_symbiosis_transmission1, k_symbiosis_transmission, by =  c("name" = "symbiosis_transmission"))  %>% left_join(pred_symbiosis_transmission)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_symbiosis_transmission <- ggplot(data = res_symbiosis_transmission1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiosis_transmission)), 
                   aes(x= tanh(Zr), y = symbiosis_transmission, size = ((1/VZr) + 3), colour = symbiosis_transmission), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values =   c("MutualistBoth"= colour_ls[1], "MutualistHorizontal"= colour_ls[2], "MutualistVertical" = colour_ls[3],"ParasiteBoth"= colour_ls[4], "ParasiteHorizontal" = colour_ls[5])) +
  scale_fill_manual(values = c("MutualistBoth"= colour_ls[1], "MutualistHorizontal"= colour_ls[2], "MutualistVertical" = colour_ls[3],"ParasiteBoth"= colour_ls[4], "ParasiteHorizontal" = colour_ls[5])) +
  scale_y_discrete(labels = c("MutualistBoth" = "Mutualist-\nBoth", "MutualistHorizontal" = "Mutualist-\nHorizontal","MutualistVertical" = "Mutualist-\nVertical", "ParasiteBoth" = "Parasite-\nBoth", "ParasiteHorizontal" = "Parasite-\nHorizontal")) +
  annotate('text', x = -1, y = res_symbiosis_transmission1$name, label= paste("italic(k)==", res_symbiosis_transmission1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_symbiosis_transmission

NOTE!!! * Do the REF REF REF * Justification of the use of combined datasets…. - done * just do the main one for all three datasets but not others * or we could - provide forest plots of all the three datasets???? (do it later) * heterogeneity - done

  • one-by-one analyses here…

The combined effect of host taxa and symbiosis (parasitism vs. mutualism)

# reordering
dat$host_tax_symbiosis <- factor(dat$host_tax_symbiosis, levels = c("MicrobeMutualist", 
    "MicrobeParasite", "PlantMutualist", "PlantParasite", "InvertMutualist", 
    "InvertParasite", "VertMutualist", "VertParasite"))

# meta-regression: mutiple intercepts
mr_host_tax_symbiosis1 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_symbiosis - 
    1, test = "t", random = ~1 | authors, data = dat)

# # meta-regression: contrasts x 10 getting the level names out
level_names <- levels(dat$host_tax_symbiosis)

# helper function to run metafor meta-regression
run_rma <- function(name) {
    rma.mv(yi = Zr, V = VZr, mods = ~relevel(host_tax_symbiosis, ref = name), 
        test = "t", random = ~1 | authors, data = dat)
}

# results of meta-regression including all contrast results; taking the last
# level out ([-length(level_names)])
mr_host_tax_symbiosis <- map(level_names[-length(level_names)], run_rma)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with host_tax_broad.

# getting marginal R2
r2_host_tax_symbiosis1 <- R2(mr_host_tax_symbiosis1)

# getting estimates
res_host_tax_symbiosis1 <- get_est(mr_host_tax_symbiosis1, mod = "host_tax_symbiosis")
res_host_tax_symbiosis <- map(mr_host_tax_symbiosis, ~get_est(.x, mod = "host_tax_symbiosis"))

# a list of the numbers to take out unnecessary contrasts
contra_list <- Map(seq, from = 1, to = 1:7)

# you need to flatten twice: first to make it a list and make it a vector
estiamtes <- map2(res_host_tax_symbiosis, contra_list, ~.x[-(.y), "estimate"]) %>% 
    flatten() %>% flatten_dbl()
lowerCLs <- map2(res_host_tax_symbiosis, contra_list, ~.x[-(.y), "lowerCL"]) %>% 
    flatten() %>% flatten_dbl()
upperCLs <- map2(res_host_tax_symbiosis, contra_list, ~.x[-(.y), "upperCL"]) %>% 
    flatten() %>% flatten_dbl()

# creating a table
tibble(`Fixed effect` = c(as.character(res_host_tax_symbiosis1$name), cont_gen(res_host_tax_symbiosis1$name)), 
    Estimate = c(res_host_tax_symbiosis1$estimate, estiamtes), `Lower CI [0.025]` = c(res_host_tax_symbiosis1$lowerCL, 
        lowerCLs), `Upper CI  [0.975]` = c(res_host_tax_symbiosis1$upperCL, 
        lowerCLs), `V[authors]` = c(mr_host_tax_symbiosis1$sigma2, rep(NA, (8 + 
        choose(8, 2)) - 1)), R2 = c(r2_host_tax_symbiosis1[1], rep(NA, (8 + 
        choose(8, 2)) - 1))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left") %>% scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
MicrobeMutualist 0.806 0.596 1.015 0.027 0.296
MicrobeParasite 0.286 0.072 0.500 NA NA
PlantMutualist 0.241 0.129 0.354 NA NA
PlantParasite 0.246 0.155 0.337 NA NA
InvertMutualist 0.424 0.348 0.500 NA NA
InvertParasite 0.348 0.210 0.486 NA NA
VertMutualist 0.674 0.143 1.206 NA NA
VertParasite 0.321 0.272 0.371 NA NA
MicrobeMutualist-MicrobeParasite -0.520 -0.819 -0.819 NA NA
MicrobeMutualist-PlantMutualist -0.565 -0.802 -0.802 NA NA
MicrobeMutualist-PlantParasite -0.560 -0.788 -0.788 NA NA
MicrobeMutualist-InvertMutualist -0.382 -0.604 -0.604 NA NA
MicrobeMutualist-InvertParasite -0.458 -0.708 -0.708 NA NA
MicrobeMutualist-VertMutualist -0.131 -0.703 -0.703 NA NA
MicrobeMutualist-VertParasite -0.484 -0.699 -0.699 NA NA
MicrobeParasite-PlantMutualist -0.045 -0.287 -0.287 NA NA
MicrobeParasite-PlantParasite -0.040 -0.272 -0.272 NA NA
MicrobeParasite-InvertMutualist 0.138 -0.089 -0.089 NA NA
MicrobeParasite-InvertParasite 0.062 -0.193 -0.193 NA NA
MicrobeParasite-VertMutualist 0.389 -0.185 -0.185 NA NA
MicrobeParasite-VertParasite 0.036 -0.184 -0.184 NA NA
PlantMutualist-PlantParasite 0.005 -0.131 -0.131 NA NA
PlantMutualist-InvertMutualist 0.183 0.047 0.047 NA NA
PlantMutualist-InvertParasite 0.107 -0.071 -0.071 NA NA
PlantMutualist-VertMutualist 0.433 -0.110 -0.110 NA NA
PlantMutualist-VertParasite 0.080 -0.042 -0.042 NA NA
PlantParasite-InvertMutualist 0.178 0.060 0.060 NA NA
PlantParasite-InvertParasite 0.102 -0.063 -0.063 NA NA
PlantParasite-VertMutualist 0.428 -0.111 -0.111 NA NA
PlantParasite-VertParasite 0.075 -0.028 -0.028 NA NA
InvertMutualist-InvertParasite -0.076 -0.234 -0.234 NA NA
InvertMutualist-VertMutualist 0.250 -0.287 -0.287 NA NA
InvertMutualist-VertParasite -0.103 -0.193 -0.193 NA NA
InvertParasite-VertMutualist 0.326 -0.223 -0.223 NA NA
InvertParasite-VertParasite -0.027 -0.170 -0.170 NA NA
VertMutualist-VertParasite -0.353 -0.887 -0.887 NA NA
# adding sample size (k) for each category
k_host_tax_symbiosis <- dat %>% group_by(host_tax_symbiosis) %>% count()
# getting estimates and predicitons
pred_host_tax_symbiosis <- get_pred(mr_host_tax_symbiosis1, mod = "host_tax_symbiosis") 
res_host_tax_symbiosis1 <- left_join(res_host_tax_symbiosis1, k_host_tax_symbiosis, by =  c("name" = "host_tax_symbiosis"))  %>% left_join(pred_host_tax_symbiosis)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_host_tax_symbiosis <- ggplot(data = res_host_tax_symbiosis1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(host_tax_symbiosis)), 
                   aes(x= tanh(Zr), y = host_tax_symbiosis, size = ((1/VZr) + 3), colour = host_tax_symbiosis), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values =   c("MicrobeMutualist"= colour_ls[1], "MicrobeParasite"= colour_ls[2],  "PlantMutualist"= colour_ls[3], "PlantParasite"= colour_ls[4], "InvertMutualist" = colour_ls[5],  "InvertParasite"= colour_ls[6], "VertMutualist"= colour_ls[7],     "VertParasite"= colour_ls[8] )) +
  scale_fill_manual(values = c("MicrobeMutualist"= colour_ls[1], "MicrobeParasite"= colour_ls[2],  "PlantMutualist"= colour_ls[3], "PlantParasite"= colour_ls[4], "InvertMutualist" = colour_ls[5],  "InvertParasite"= colour_ls[6], "VertMutualist"= colour_ls[7],     "VertParasite"= colour_ls[8] )) +
  scale_y_discrete(labels = c("MicrobeMutualist"= "Microbe-\nMutualist", "MicrobeParasite"= "Microbe-\nParasite",  "PlantMutualist" = "Plant-\nMutualist", "PlantParasite"="Plant-\nParasite", "InvertMutualist" = "Invertebrate-\nMutualist",   "InvertParasite"= "Invertebrate-\nParasite", "VertMutualist"= "Vertebrate-\nMutualist",  "VertParasite"= "Vertebrate-\nParasite" )) +
  annotate('text', x = -1, y = res_host_tax_symbiosis1$name, label= paste("italic(k)==", res_host_tax_symbiosis1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_host_tax_symbiosis

Supplementary Figure 3:

The combined effect of symbiont taxa and symbiosis (parasitism vs. mutualism)

NOTE - symbiont_tax_symbiosis = 21 combinations

# reordering
dat$symbiont_tax_symbiosis <- factor(dat$symbiont_tax_symbiosis, levels = c("MicrobeMutualist", 
    "MicrobeParasite", "PlantMutualist", "PlantParasite", "InvertMutualist", 
    "InvertParasite", "VertParasite"))

# meta-regression: multiple intercepts
mr_symbiont_tax_symbiosis1 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiont_tax_symbiosis - 
    1, test = "t", random = ~1 | authors, data = dat)

# # meta-regression: contrasts x 10 getting the level names out
level_names <- levels(dat$symbiont_tax_symbiosis)

# helper function to run metafor meta-regression
run_rma <- function(name) {
    rma.mv(yi = Zr, V = VZr, mods = ~relevel(symbiont_tax_symbiosis, ref = name), 
        test = "t", random = ~1 | authors, data = dat)
}

# results of meta-regression including all contrast results; taking the last
# level out ([-length(level_names)])
mr_symbiont_tax_symbiosis <- map(level_names[-length(level_names)], run_rma)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with host_tax_broad.

# getting marginal R2
r2_symbiont_tax_symbiosis1 <- R2(mr_symbiont_tax_symbiosis1)

# getting estimates
res_symbiont_tax_symbiosis1 <- get_est(mr_symbiont_tax_symbiosis1, mod = "symbiont_tax_symbiosis")
res_symbiont_tax_symbiosis <- map(mr_symbiont_tax_symbiosis, ~get_est(.x, mod = "symbiont_tax_symbiosis"))

# a list of the numbers to take out unnecessary contrasts
contra_list <- Map(seq, from = 1, to = 1:6)

# you need to flatten twice: first to make it a list and make it a vector
estiamtes <- map2(res_symbiont_tax_symbiosis, contra_list, ~.x[-(.y), "estimate"]) %>% 
    flatten() %>% flatten_dbl()
lowerCLs <- map2(res_symbiont_tax_symbiosis, contra_list, ~.x[-(.y), "lowerCL"]) %>% 
    flatten() %>% flatten_dbl()
upperCLs <- map2(res_symbiont_tax_symbiosis, contra_list, ~.x[-(.y), "upperCL"]) %>% 
    flatten() %>% flatten_dbl()

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiont_tax_symbiosis1$name), cont_gen(res_symbiont_tax_symbiosis1$name)), 
    Estimate = c(res_symbiont_tax_symbiosis1$estimate, estiamtes), `Lower CI [0.025]` = c(res_symbiont_tax_symbiosis1$lowerCL, 
        lowerCLs), `Upper CI  [0.975]` = c(res_symbiont_tax_symbiosis1$upperCL, 
        lowerCLs), `V[authors]` = c(mr_symbiont_tax_symbiosis1$sigma2, rep(NA, 
        (7 + choose(7, 2)) - 1)), R2 = c(r2_symbiont_tax_symbiosis1[1], rep(NA, 
        (7 + choose(7, 2)) - 1))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left") %>% scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
MicrobeMutualist 0.437 0.365 0.509 0.029 0.263
MicrobeParasite 0.279 0.213 0.345 NA NA
PlantMutualist 0.651 0.348 0.953 NA NA
PlantParasite 1.499 0.555 2.443 NA NA
InvertMutualist 0.290 0.165 0.415 NA NA
InvertParasite 0.325 0.269 0.380 NA NA
VertParasite 0.291 -0.100 0.681 NA NA
MicrobeMutualist-MicrobeParasite -0.158 -0.256 -0.256 NA NA
MicrobeMutualist-PlantMutualist 0.214 -0.097 -0.097 NA NA
MicrobeMutualist-PlantParasite 1.062 0.115 0.115 NA NA
MicrobeMutualist-InvertMutualist -0.147 -0.291 -0.291 NA NA
MicrobeMutualist-InvertParasite -0.112 -0.203 -0.203 NA NA
MicrobeMutualist-VertParasite -0.146 -0.543 -0.543 NA NA
MicrobeParasite-PlantMutualist 0.372 0.062 0.062 NA NA
MicrobeParasite-PlantParasite 1.220 0.274 0.274 NA NA
MicrobeParasite-InvertMutualist 0.011 -0.130 -0.130 NA NA
MicrobeParasite-InvertParasite 0.046 -0.040 -0.040 NA NA
MicrobeParasite-VertParasite 0.012 -0.384 -0.384 NA NA
PlantMutualist-PlantParasite 0.848 -0.143 -0.143 NA NA
PlantMutualist-InvertMutualist -0.361 -0.688 -0.688 NA NA
PlantMutualist-InvertParasite -0.326 -0.634 -0.634 NA NA
PlantMutualist-VertParasite -0.360 -0.854 -0.854 NA NA
PlantParasite-InvertMutualist -1.208 -2.161 -2.161 NA NA
PlantParasite-InvertParasite -1.174 -2.120 -2.120 NA NA
PlantParasite-VertParasite -1.208 -2.229 -2.229 NA NA
InvertMutualist-InvertParasite 0.034 -0.099 -0.099 NA NA
InvertMutualist-VertParasite 0.001 -0.409 -0.409 NA NA
InvertParasite-VertParasite -0.034 -0.428 -0.428 NA NA
# adding sample size (k) for each category
k_symbiont_tax_symbiosis <- dat %>% group_by(symbiont_tax_symbiosis) %>% count()
# getting estimates and predicitons
pred_symbiont_tax_symbiosis <- get_pred(mr_symbiont_tax_symbiosis1, mod = "symbiont_tax_symbiosis") 
res_symbiont_tax_symbiosis1 <- left_join(res_symbiont_tax_symbiosis1, k_symbiont_tax_symbiosis, by =  c("name" = "symbiont_tax_symbiosis"))  %>% left_join(pred_symbiont_tax_symbiosis)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_symbiont_tax_symbiosis <- ggplot(data = res_symbiont_tax_symbiosis1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiont_tax_symbiosis)), 
                   aes(x= tanh(Zr), y = symbiont_tax_symbiosis, size = ((1/VZr) + 3), colour = symbiont_tax_symbiosis), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  # setting colours
  scale_color_manual(values =   c("MicrobeMutualist"= colour_ls[1], "MicrobeParasite"= colour_ls[2],  "PlantMutualist"= colour_ls[3], "PlantParasite"= colour_ls[4], "InvertMutualist" = colour_ls[5],  "InvertParasite"= colour_ls[6], "VertParasite"= colour_ls[8] )) +
  scale_fill_manual(values = c("MicrobeMutualist"= colour_ls[1], "MicrobeParasite"= colour_ls[2],  "PlantMutualist"= colour_ls[3], "PlantParasite"= colour_ls[4], "InvertMutualist" = colour_ls[5],  "InvertParasite"= colour_ls[6], "VertParasite"= colour_ls[8] )) +
  scale_y_discrete(labels = c("MicrobeMutualist"= "Microbe-\nMutualist", "MicrobeParasite"= "Microbe-\nParasite",  "PlantMutualist" = "Plant-\nMutualist", "PlantParasite"="Plant-\nParasite", "InvertMutualist" = "Invertebrate-\nMutualist",   "InvertParasite"= "Invertebrate-\nParasite",  "VertParasite"= "Vertebrate-\nParasite" )) +
  annotate('text', x = -1, y = res_symbiont_tax_symbiosis1$name, label= paste("italic(k)==", res_symbiont_tax_symbiosis1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0, 1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_symbiont_tax_symbiosis

Supplementary Figure 4:

The combined effect of host and symbiont taxa

NOTE – host_symbiont_tax - 11 varaibles and 55 combinations!!!!

# reordering
dat$host_symbiont_tax <- factor(dat$host_symbiont_tax, levels = c("MicrobeInvert", 
    "MicrobeMicrobe", "MicrobePlant", "PlantInvert", "PlantMicrobe", "InvertInvert", 
    "InvertMicrobe", "InvertPlant", "VertInvert", "VertMicrobe", "VertVert"))

# meta-regression: multiple intercepts
mr_host_symbiont_tax1 <- rma.mv(yi = Zr, V = VZr, mods = ~host_symbiont_tax - 
    1, test = "t", random = ~1 | authors, data = dat)

# # meta-regression: contrasts x 10 getting the level names out
level_names <- levels(dat$host_symbiont_tax)

# helper function to run metafor meta-regression
run_rma <- function(name) {
    rma.mv(yi = Zr, V = VZr, mods = ~relevel(host_symbiont_tax, ref = name), 
        test = "t", random = ~1 | authors, data = dat)
}

# results of meta-regression including all contrast results; taking the last
# level out ([-length(level_names)])
mr_host_symbiont_tax <- map(level_names[-length(level_names)], run_rma)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with host_tax_broad.

# getting marginal R2
r2_host_symbiont_tax1 <- R2(mr_host_symbiont_tax1)

# getting estimates
res_host_symbiont_tax1 <- get_est(mr_host_symbiont_tax1, mod = "host_symbiont_tax")
res_host_symbiont_tax <- map(mr_host_symbiont_tax, ~get_est(.x, mod = "host_symbiont_tax"))

# a list of the numbers to take out unnecessary contrasts
contra_list <- Map(seq, from = 1, to = 1:10)

# you need to flatten twice: first to make it a list and make it a vector
estiamtes <- map2(res_host_symbiont_tax, contra_list, ~.x[-(.y), "estimate"]) %>% 
    flatten() %>% flatten_dbl()

lowerCLs <- map2(res_host_symbiont_tax, contra_list, ~.x[-(.y), "lowerCL"]) %>% 
    flatten() %>% flatten_dbl()

upperCLs <- map2(res_host_symbiont_tax, contra_list, ~.x[-(.y), "upperCL"]) %>% 
    flatten() %>% flatten_dbl()

# creating a table
tibble(`Fixed effect` = c(as.character(res_host_symbiont_tax1$name), cont_gen(res_host_symbiont_tax1$name)), 
    Estimate = c(res_host_symbiont_tax1$estimate, estiamtes), `Lower CI [0.025]` = c(res_host_symbiont_tax1$lowerCL, 
        lowerCLs), `Upper CI  [0.975]` = c(res_host_symbiont_tax1$upperCL, lowerCLs), 
    `V[authors]` = c(mr_host_tax_symbiosis1$sigma2, rep(NA, (11 + choose(11, 
        2)) - 1)), R2 = c(r2_host_symbiont_tax1[1], rep(NA, (11 + choose(11, 
        2)) - 1))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left") %>% scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
MicrobeInvert 0.623 -0.119 1.366 0.027 0.22
MicrobeMicrobe 0.508 0.328 0.689 NA NA
MicrobePlant 0.696 0.379 1.012 NA NA
PlantInvert 0.216 0.119 0.312 NA NA
PlantMicrobe 0.295 0.167 0.423 NA NA
InvertInvert 0.421 0.286 0.556 NA NA
InvertMicrobe 0.405 0.325 0.485 NA NA
InvertPlant 0.929 0.187 1.672 NA NA
VertInvert 0.355 0.287 0.422 NA NA
VertMicrobe 0.293 0.215 0.371 NA NA
VertVert 0.291 -0.107 0.688 NA NA
MicrobeInvert-MicrobeMicrobe -0.115 -0.879 -0.879 NA NA
MicrobeInvert-MicrobePlant 0.072 -0.735 -0.735 NA NA
MicrobeInvert-PlantInvert -0.408 -1.157 -1.157 NA NA
MicrobeInvert-PlantMicrobe -0.328 -1.082 -1.082 NA NA
MicrobeInvert-InvertInvert -0.202 -0.957 -0.957 NA NA
MicrobeInvert-InvertMicrobe -0.218 -0.965 -0.965 NA NA
MicrobeInvert-InvertPlant 0.306 -0.744 -0.744 NA NA
MicrobeInvert-VertInvert -0.269 -1.014 -1.014 NA NA
MicrobeInvert-VertMicrobe -0.330 -1.077 -1.077 NA NA
MicrobeInvert-VertVert -0.332 -1.174 -1.174 NA NA
MicrobeMicrobe-MicrobePlant 0.187 -0.177 -0.177 NA NA
MicrobeMicrobe-PlantInvert -0.293 -0.498 -0.498 NA NA
MicrobeMicrobe-PlantMicrobe -0.213 -0.435 -0.435 NA NA
MicrobeMicrobe-InvertInvert -0.087 -0.313 -0.313 NA NA
MicrobeMicrobe-InvertMicrobe -0.103 -0.301 -0.301 NA NA
MicrobeMicrobe-InvertPlant 0.421 -0.343 -0.343 NA NA
MicrobeMicrobe-VertInvert -0.154 -0.347 -0.347 NA NA
MicrobeMicrobe-VertMicrobe -0.215 -0.412 -0.412 NA NA
MicrobeMicrobe-VertVert -0.217 -0.654 -0.654 NA NA
MicrobePlant-PlantInvert -0.480 -0.811 -0.811 NA NA
MicrobePlant-PlantMicrobe -0.401 -0.742 -0.742 NA NA
MicrobePlant-InvertInvert -0.274 -0.618 -0.618 NA NA
MicrobePlant-InvertMicrobe -0.290 -0.617 -0.617 NA NA
MicrobePlant-InvertPlant 0.234 -0.574 -0.574 NA NA
MicrobePlant-VertInvert -0.341 -0.665 -0.665 NA NA
MicrobePlant-VertMicrobe -0.403 -0.728 -0.728 NA NA
MicrobePlant-VertVert -0.405 -0.913 -0.913 NA NA
PlantInvert-PlantMicrobe 0.080 -0.081 -0.081 NA NA
PlantInvert-InvertInvert 0.206 0.040 0.040 NA NA
PlantInvert-InvertMicrobe 0.190 0.064 0.064 NA NA
PlantInvert-InvertPlant 0.714 -0.035 -0.035 NA NA
PlantInvert-VertInvert 0.139 0.021 0.021 NA NA
PlantInvert-VertMicrobe 0.078 -0.047 -0.047 NA NA
PlantInvert-VertVert 0.075 -0.334 -0.334 NA NA
PlantMicrobe-InvertInvert 0.126 -0.060 -0.060 NA NA
PlantMicrobe-InvertMicrobe 0.110 -0.041 -0.041 NA NA
PlantMicrobe-InvertPlant 0.634 -0.119 -0.119 NA NA
PlantMicrobe-VertInvert 0.059 -0.085 -0.085 NA NA
PlantMicrobe-VertMicrobe -0.002 -0.152 -0.152 NA NA
PlantMicrobe-VertVert -0.004 -0.422 -0.422 NA NA
InvertInvert-InvertMicrobe -0.016 -0.173 -0.173 NA NA
InvertInvert-InvertPlant 0.508 -0.247 -0.247 NA NA
InvertInvert-VertInvert -0.067 -0.211 -0.211 NA NA
InvertInvert-VertMicrobe -0.128 -0.284 -0.284 NA NA
InvertInvert-VertVert -0.130 -0.550 -0.550 NA NA
InvertMicrobe-InvertPlant 0.524 -0.223 -0.223 NA NA
InvertMicrobe-VertInvert -0.051 -0.156 -0.156 NA NA
InvertMicrobe-VertMicrobe -0.112 -0.224 -0.224 NA NA
InvertMicrobe-VertVert -0.114 -0.520 -0.520 NA NA
InvertPlant-VertInvert -0.575 -1.320 -1.320 NA NA
InvertPlant-VertMicrobe -0.636 -1.383 -1.383 NA NA
InvertPlant-VertVert -0.638 -1.481 -1.481 NA NA
VertInvert-VertMicrobe -0.061 -0.165 -0.165 NA NA
VertInvert-VertVert -0.064 -0.467 -0.467 NA NA
VertMicrobe-VertVert -0.002 -0.407 -0.407 NA NA
# colour list
#colour_ls <- c("#000000", "#E69F00", "#56B4E9", "#009E73",  "#F0E422",  "#0072B2",  "#D55E00", "#CC79A7", "#00008B", "#8B0A50", "#54FF9F", "#999999")

# adding sample size (k) for each category
k_host_symbiont_tax <- dat %>% group_by(host_symbiont_tax) %>% count()
# getting estimates and predicitons
pred_host_symbiont_tax <- get_pred(mr_host_symbiont_tax1, mod = "host_symbiont_tax") 
res_host_symbiont_tax1 <- left_join(res_host_symbiont_tax1, k_host_symbiont_tax, by =  c("name" = "host_symbiont_tax"))  %>% left_join(pred_host_symbiont_tax)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_host_symbiont_tax <- ggplot(data = res_host_symbiont_tax1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(host_symbiont_tax)), 
                   aes(x= tanh(Zr), y = host_symbiont_tax, size = ((1/VZr) + 3), colour = host_symbiont_tax), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values =  c("MicrobeInvert" = colour_ls[1],  "MicrobeMicrobe"= colour_ls[2], "MicrobePlant" = colour_ls[3], "PlantInvert" = colour_ls[4],"PlantMicrobe" = colour_ls[5], "InvertInvert"  = colour_ls[6],  "InvertMicrobe" = colour_ls[7], "InvertPlant" = colour_ls[8],"VertInvert"  = colour_ls[9], "VertMicrobe"= colour_ls[10],"VertVert"  = colour_ls[11])) +
  scale_fill_manual(values = c("MicrobeInvert" = colour_ls[1],  "MicrobeMicrobe"= colour_ls[2], "MicrobePlant" = colour_ls[3], "PlantInvert" = colour_ls[4],"PlantMicrobe" = colour_ls[5], "InvertInvert"  = colour_ls[6],  "InvertMicrobe" = colour_ls[7], "InvertPlant" = colour_ls[8],"VertInvert"  = colour_ls[9], "VertMicrobe"= colour_ls[10],"VertVert"  = colour_ls[11])) +
  scale_y_discrete(labels = c("MicrobeInvert" = "Microbe-\nInvertebrate",  "MicrobeMicrobe"= "Microbe-\nMicrobe", "MicrobePlant" = "Microbe-\nPlant", "PlantInvert" = "Plant-\nInvertebrate","PlantMicrobe" = "Plant-\nMicrobe", "InvertInvert"  = "Invertebrate\nInvertebrate",  "InvertMicrobe" = "Invertebrate-\nMicrobe", "InvertPlant" = "Invertebrate-\nPlant","VertInvert"  = "Vertebrate-\nInvertebrate", "VertMicrobe"= "Vertebrate-\nMicrobe", "VertVert"  = "Vertebrate-\nVertebrate")) +
  annotate('text', x = -1, y = res_host_symbiont_tax1$name, label= paste("italic(k)==", res_host_symbiont_tax1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlaton)")), y = "", size = expression(paste(italic(n), " (# of species)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_host_symbiont_tax

Supplementary Figure 4:

Addtional analyses

Model selection (Mulit-predictor model)

# creates a new function to run in MuMIn
updated.rma.mv <- updateable(rma.mv)
# updated.rma.mv

# testing the new function use method = 'ML' so that we can compare AIC
mr_full <- updated.rma.mv(yi = Zr, V = VZr, mods = ~symbiosis + host_tax_broad + 
    symbiont_tax_broad + mode_of_transmission_broad + endo_or_ecto + log(host_range_link_ratio), 
    test = "t", random = ~1 | authors, method = "ML", data = dat)

# summary(mr_full) # testing call of new function getCall(mr_full) # update
# the new function to run in MuMIn update(mr_full)

# ============================= additional methods for 'rma.mv' class (made
# by Kamil Barton) we need this to run model selection with rma.mv in MuMIn
# =============================
formula.rma.mv <- function(x, ...) return(eval(getCall(x)$mods))

makeArgs.rma.mv <- function(obj, termNames, comb, opt, ...) {
    ret <- MuMIn:::makeArgs.default(obj, termNames, comb, opt)
    names(ret)[1L] <- "mods"
    ret
}

nobs.rma.mv <- function(object, ...) attr(logLik(object), "nall")

coefTable.rma.mv <- function(model, ...) MuMIn:::.makeCoefTable(model$b, model$se, 
    coefNames = rownames(model$b))
# =============================

# testing dredge dredge(full.model, evaluate=F) # show all candidate models
# n = 32 model exisit
candidates <- dredge(mr_full)

# displays delta AICc <2
candidates_aic2 <- subset(candidates, delta < 2)

# model averaging it seems like models are using z values rather than t
# values (which will be OK)
mr_averaged_aic2 <- summary(model.avg(candidates, delta < 2))

# relative importance of each predictor
importance <- importance(candidates)

# use REML if not for model comparision
model1 <- rma.mv(yi = Zr, V = VZr, mods = ~mode_of_transmission_broad + host_tax_broad, 
    test = "t", random = ~1 | authors, method = "REML", data = dat)
model2 <- rma.mv(yi = Zr, V = VZr, mods = ~mode_of_transmission_broad + host_tax_broad + 
    symbiosis, test = "t", random = ~1 | authors, method = "REML", data = dat)

** table model aic etc

# creating a table
tibble(`Model (variable weight)` = c("Model1", "Model2", "(Sum of weights)"), 
    transmission = c(if_else(candidates_aic2$mode_of_transmission_broad == "+", 
        "$+$", "NA"), round(importance[1], 3)), host_tax = c(if_else(candidates_aic2$host_tax_broad == 
        "+", "$+$", "NA"), round(importance[2], 3)), symbiosis = c(if_else(candidates_aic2$symbiosis == 
        "+", "$+$", "NA"), round(importance[3], 3)), symbiont_tax = c(if_else(candidates_aic2$symbiont_tax_broad == 
        "+", "$+$", "NA"), round(importance[4], 3)), endo_or_ecto = c(if_else(candidates_aic2$endo_or_ecto == 
        "+", "$+$", "NA"), round(importance[5], 3)), host_range = c(if_else(candidates_aic2$`log(host_range_link_ratio)` == 
        "+", "$+$", "NA"), round(importance[6], 3)), delta_AICc = c(candidates_aic2$delta, 
        NA), Weight = c(candidates_aic2$weight, NA)) %>% kable("html", digits = 3) %>% 
    kable_styling("striped", position = "left")
Model (variable weight) transmission host_tax symbiosis symbiont_tax endo_or_ecto host_range delta_AICc Weight
Model1 \(+\) \(+\) NA NA NA NA 0.000 0.633
Model2 \(+\) \(+\) \(+\) NA NA NA 1.087 0.367
(Sum of weights) 0.998 0.682 0.342 0.217 0.129 0.087 NA NA

** model averaged estiamtes (full average)

# getting averaged R2 and variance components not provided by the MuMIn
# package
average_sigma2 <- weighted.mean(x = c(model1$sigma2, model2$sigma2), w = candidates_aic2$weight)
average_R2 <- weighted.mean(x = c(R2(model1)[1], R2(model2)[1]), w = candidates_aic2$weight)

# creating a table
tibble(`Fixed effect` = c("Intercept (both-Microbe-Mutulist)", "Microbe-Plant", 
    "Microbe-Invert", "Microbe-Vert", "both-horizontal", "both-vertical", "Mutulist-Parasite"), 
    Estimate = mr_averaged_aic2$coefmat.full[, 1], `Lower CI [0.025]` = mr_averaged_aic2$coefmat.full[, 
        1] - mr_averaged_aic2$coefmat.full[, 2] * qnorm(0.975), `Upper CI  [0.975]` = mr_averaged_aic2$coefmat.full[, 
        1] + mr_averaged_aic2$coefmat.full[, 2] * qnorm(0.975), `V[authors]` = c(average_sigma2, 
        rep(NA, 6)), R2 = c(average_R2, rep(NA, 6))) %>% kable("html", digits = 3) %>% 
    kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept (both-Microbe-Mutulist) 0.547 0.382 0.711 0.024 0.282
Microbe-Plant -0.248 -0.417 -0.078 NA NA
Microbe-Invert -0.185 -0.355 -0.015 NA NA
Microbe-Vert -0.173 -0.332 -0.014 NA NA
both-horizontal -0.055 -0.141 0.032 NA NA
both-vertical 0.120 -0.031 0.271 NA NA
Mutulist-Parasite -0.016 -0.095 0.062 NA NA

Publication Bias and Sensitivity Analysis

  • boundary problems ** no of randomzations and limit_rearched
  • Time lag bias

Residual funnel plot 1

# 
res_funnel_plot <- rma.mv(yi = Zr, V = VZr, mods = ~mode_of_transmission_broad + 
    host_tax_broad + symbiosis, random = ~1 | authors, data = dat)

funnel(res_funnel_plot, yaxis = "seinv")

Supplementary Figure 5:

Univaraite Egger regression

# 
egger_regression_uni <- rma.mv(yi = Zr, V = VZr, mods = ~sqrt(VZr), random = ~1 | 
    authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_egger_regression_uni <- R2(egger_regression_uni)

# getting estimates: name does not work for slopes
res_egger_regression_uni <- get_est(egger_regression_uni, mod = "sqrt(VZr)")

# creating a table
tibble(`Fixed effect` = c("Intercept", "sqrt(VZr)"), Estimate = c(res_egger_regression_uni$estimate), 
    `Lower CI [0.025]` = c(res_egger_regression_uni$lowerCL), `Upper CI  [0.975]` = c(res_egger_regression_uni$upperCL), 
    `V[authors]` = c(egger_regression_uni$sigma2, NA), R2 = c(r2_egger_regression_uni[1], 
        NA)) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept 0.124 0.035 0.212 0.026 0.255
sqrt(VZr) 1.314 0.817 1.810 NA NA
pred_egger_regression_uni <- predict.rma(egger_regression_uni)

# plotting

fit_egger_regression_uni <- dat %>% mutate(ymin = pred_egger_regression_uni$ci.lb, 
    ymax = pred_egger_regression_uni$ci.ub, ymin2 = pred_egger_regression_uni$cr.lb, 
    ymax2 = pred_egger_regression_uni$cr.ub, pred = pred_egger_regression_uni$pred) %>% 
    ggplot(aes(x = sqrt(VZr), y = Zr, size = (1/VZr) + 3)) + geom_point(shape = 21, 
    fill = "grey90") + # geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = '#0072B2') + # not quite
# sure why this does not work
geom_smooth(aes(y = ymin2), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
    colour = "#0072B2") + geom_smooth(aes(y = ymax2), method = "loess", se = FALSE, 
    lty = "dotted", lwd = 0.25, colour = "#0072B2") + geom_smooth(aes(y = ymin), 
    method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#D55E00") + 
    geom_smooth(aes(y = ymax), method = "loess", se = FALSE, lty = "dotted", 
        lwd = 0.25, colour = "#D55E00") + geom_smooth(aes(y = pred), method = "loess", 
    se = FALSE, lty = "dashed", lwd = 0.5, colour = "black") + ylim(-1, 2) + 
    xlim(0.05, 0.45) + # geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope =
# mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = 'dashed', size
# = 0.5) +
labs(x = "sqrt(sampling variance)", y = expression(paste(italic(Zr), " (effect size)")), 
    size = expression(paste(italic(n), " (# of species)"))) + guides(fill = "none", 
    colour = "none") + # themses
theme_bw() + theme(legend.position = c(0, 1), legend.justification = c(0, 1)) + 
    theme(legend.direction = "horizontal") + # theme(legend.background = element_rect(fill = 'white', colour = 'black'))
# +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90))

fit_egger_regression_uni

Multivaraite Egger regression

# 
egger_regression_mul <- rma.mv(yi = Zr, V = VZr, mods = ~sqrt(VZr) + mode_of_transmission_broad + 
    host_tax_broad + symbiosis, random = ~1 | authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_egger_regression_mul <- R2(egger_regression_mul)

# creating a table
tibble(`Fixed effect` = c("Intercept (both-Microbe-Mutulist)", "sqrt(VZr)", 
    "both-horizontal", "both-vertical", "Microbe-Plant", "Microbe-Invert", "Microbe-Vert", 
    "Mutulist-Parasite"), Estimate = c(egger_regression_mul$b), `Lower CI [0.025]` = c(egger_regression_mul$ci.lb), 
    `Upper CI  [0.975]` = c(egger_regression_mul$ci.ub), `V[authors]` = c(egger_regression_mul$sigma2, 
        rep(NA, 7)), R2 = c(r2_egger_regression_mul[1], rep(NA, 7))) %>% kable("html", 
    digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept (both-Microbe-Mutulist) 0.290 0.094 0.486 0.018 0.478
sqrt(VZr) 1.202 0.726 1.678 NA NA
both-horizontal -0.043 -0.125 0.039 NA NA
both-vertical 0.138 -0.016 0.291 NA NA
Microbe-Plant -0.167 -0.331 -0.002 NA NA
Microbe-Invert -0.145 -0.309 0.019 NA NA
Microbe-Vert -0.095 -0.251 0.062 NA NA
Mutulist-Parasite -0.040 -0.144 0.065 NA NA
pred_egger_regression_mul <-predict.rma(egger_regression_mul) 

# plotting

fit_egger_regression_mul <-  dat %>% 
  filter(!is.na(mode_of_transmission_broad) & !is.na(host_tax_broad) & !is.na(symbiosis))  %>% # getting ride of NA values
  mutate(ymin = pred_egger_regression_mul$ci.lb, 
         ymax = pred_egger_regression_mul$ci.ub,
         ymin2 = pred_egger_regression_mul$cr.lb,
         ymax2 = pred_egger_regression_mul$cr.ub,
         pred = pred_egger_regression_mul$pred) %>% 
  ggplot(aes(x = sqrt(VZr), y = Zr, size = (1/VZr) + 3)) +
  geom_point(shape = 21, fill = "grey90") +
  #geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = "#0072B2")  + # not quite sure why this does not work
  geom_smooth(aes(y = ymin2), method =  "loess", se = FALSE, lty =  "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymax2), method =  "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymin), method =  "loess", se = FALSE,lty = "dotted", lwd = 0.25, colour ="#D55E00") +
  geom_smooth(aes(y = ymax), method =  "loess", se = FALSE, lty ="dotted", lwd = 0.25, colour ="#D55E00") + 
  geom_smooth(aes(y = pred), method =  "loess", se = FALSE, lty ="dashed", lwd = 0.5, colour ="black") +  
  ylim(-1, 2) + xlim(0.05, 0.45) +
  #geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope = mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = "dashed", size = 0.5) +
  labs(x = "sqrt(sampling variance)", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), " (# of species)"))) +
  guides(fill = "none", colour = "none") +
  # themses
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0, 1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fit_egger_regression_mul

Supplementary Figure 5:

it is not linear becuase these are

Residual funnel plot 2

# 
res_funnel_plot2 <- rma.mv(yi = Zr, V = VZr, mods = ~sqrt(VZr) + mode_of_transmission_broad + 
    host_tax_broad + symbiosis, random = ~1 | authors, data = dat)

funnel(res_funnel_plot2, yaxis = "seinv")

Supplementary Figure 6:

Univaraite time-lag bias

# 
time_lag_effect_uni <- rma.mv(yi = Zr, V = VZr, mods = ~year, random = ~1 | 
    authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_time_lag_effect_uni <- R2(time_lag_effect_uni)

# getting estimates: name does not work for slopes
res_time_lag_effect_uni <- get_est(time_lag_effect_uni, mod = "year")

# creating a table
tibble(`Fixed effect` = c("Intercept", "Year"), Estimate = c(res_time_lag_effect_uni$estimate), 
    `Lower CI [0.025]` = c(res_time_lag_effect_uni$lowerCL), `Upper CI  [0.975]` = c(res_time_lag_effect_uni$upperCL), 
    `V[authors]` = c(time_lag_effect_uni$sigma2, NA), R2 = c(r2_time_lag_effect_uni[1], 
        NA)) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept -2.547 -14.985 9.892 0.033 0.002
Year 0.001 -0.005 0.008 NA NA
pred_time_lag_effect_uni <- predict.rma(time_lag_effect_uni)

# plotting

fit_time_lag_effect <- dat %>% mutate(ymin = pred_time_lag_effect_uni$ci.lb, 
    ymax = pred_time_lag_effect_uni$ci.ub, ymin2 = pred_time_lag_effect_uni$cr.lb, 
    ymax2 = pred_time_lag_effect_uni$cr.ub, pred = pred_time_lag_effect_uni$pred) %>% 
    ggplot(aes(x = year, y = Zr, size = (1/VZr) + 3)) + geom_point(shape = 21, 
    fill = "grey90") + # geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = '#0072B2') + # not quite
# sure why this does not work
geom_smooth(aes(y = ymin2), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
    colour = "#0072B2") + geom_smooth(aes(y = ymax2), method = "loess", se = FALSE, 
    lty = "dotted", lwd = 0.25, colour = "#0072B2") + geom_smooth(aes(y = ymin), 
    method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#D55E00") + 
    geom_smooth(aes(y = ymax), method = "loess", se = FALSE, lty = "dotted", 
        lwd = 0.25, colour = "#D55E00") + geom_smooth(aes(y = pred), method = "loess", 
    se = FALSE, lty = "dashed", lwd = 0.5, colour = "black") + ylim(-1, 2) + 
    xlim(1994, 2019) + scale_x_continuous(breaks = c(1995, 2000, 2005, 2010, 
    2015, 2020)) + # geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope =
# mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = 'dashed', size
# = 0.5) +
labs(x = "Year", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), 
    " (# of species)"))) + guides(fill = "none", colour = "none") + # themses
theme_bw() + theme(legend.position = c(0, 1), legend.justification = c(0, 1)) + 
    theme(legend.direction = "horizontal") + # theme(legend.background = element_rect(fill = 'white', colour = 'black'))
# +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90))

fit_time_lag_effect

Supplementary Figure 6:

Multivaraite time-lag bias

# 
time_lag_effect_mul <- rma.mv(yi = Zr, V = VZr, mods = ~year + mode_of_transmission_broad + 
    host_tax_broad + symbiosis, random = ~1 | authors, data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_time_lag_effect_mul <- R2(time_lag_effect_mul)

# creating a table
tibble(`Fixed effect` = c("Intercept (both-Microbe-Mutulist)", "Year", "both-horizontal", 
    "both-vertical", "Microbe-Plant", "Microbe-Invert", "Microbe-Vert", "Mutulist-Parasite"), 
    Estimate = c(time_lag_effect_mul$b), `Lower CI [0.025]` = c(time_lag_effect_mul$ci.lb), 
    `Upper CI  [0.975]` = c(time_lag_effect_mul$ci.ub), `V[authors]` = c(time_lag_effect_mul$sigma2, 
        rep(NA, 7)), R2 = c(r2_time_lag_effect_mul[1], rep(NA, 7))) %>% kable("html", 
    digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept (both-Microbe-Mutulist) 1.221 -10.447 12.890 0.024 0.28
Year 0.000 -0.006 0.005 NA NA
both-horizontal -0.053 -0.141 0.036 NA NA
both-vertical 0.101 -0.064 0.265 NA NA
Microbe-Plant -0.255 -0.428 -0.082 NA NA
Microbe-Invert -0.187 -0.361 -0.014 NA NA
Microbe-Vert -0.168 -0.333 -0.003 NA NA
Mutulist-Parasite -0.045 -0.156 0.067 NA NA
pred_time_lag_effect_mul <- predict.rma(time_lag_effect_mul)

# plotting
fit_time_lag_effect_mul <- dat %>% filter(!is.na(mode_of_transmission_broad) & 
    !is.na(host_tax_broad) & !is.na(symbiosis)) %>% mutate(ymin = pred_time_lag_effect_mul$ci.lb, 
    ymax = pred_time_lag_effect_mul$ci.ub, ymin2 = pred_time_lag_effect_mul$cr.lb, 
    ymax2 = pred_time_lag_effect_mul$cr.ub, pred = pred_time_lag_effect_mul$pred) %>% 
    ggplot(aes(x = year, y = Zr, size = (1/VZr) + 3)) + geom_point(shape = 21, 
    fill = "grey90") + # geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = '#0072B2') + # not quite
# sure why this does not work
geom_smooth(aes(y = ymin2), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
    colour = "#0072B2") + geom_smooth(aes(y = ymax2), method = "loess", se = FALSE, 
    lty = "dotted", lwd = 0.25, colour = "#0072B2") + geom_smooth(aes(y = ymin), 
    method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#D55E00") + 
    geom_smooth(aes(y = ymax), method = "loess", se = FALSE, lty = "dotted", 
        lwd = 0.25, colour = "#D55E00") + geom_smooth(aes(y = pred), method = "loess", 
    se = FALSE, lty = "dashed", lwd = 0.5, colour = "black") + ylim(-1, 2) + 
    xlim(1994, 2019) + scale_x_continuous(breaks = c(1995, 2000, 2005, 2010, 
    2015, 2020)) + # geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope =
# mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = 'dashed', size
# = 0.5) +
labs(x = "Year", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), 
    " (# of species)"))) + guides(fill = "none", colour = "none") + # themses
theme_bw() + theme(legend.position = c(0, 1), legend.justification = c(0, 1)) + 
    theme(legend.direction = "horizontal") + # theme(legend.background = element_rect(fill = 'white', colour = 'black'))
# +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90))

fit_time_lag_effect_mul

Supplementary Figure 6: - not linear

Sensitivity test 1: the number of randamizations

  • boundary problems ** no of randomzations and limit_rearched = if they are different, then, it could lead to bias ** limit_reached = if high - more likley to be underestiamted

The type of symbiosis: parasitism vs. mutualism

# 233 --- Yes = 74 (0.3175966%); No = 159

# symbiosis multiple intercepts
sa_random_symbiosis1 <- lmer(log(no_randomizations) ~ symbiosis - 1 + (1 | authors), 
    data = dat)
# contrast
sa_random_symbiosis2 <- lmer(log(no_randomizations) ~ symbiosis + (1 | authors), 
    data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_sa_random_symbiosis <- r2_nakagawa(sa_random_symbiosis1)

# getting estimates

res_sa_random_symbiosis <- tibble(estiamte = c(fixef(sa_random_symbiosis1), 
    fixef(sa_random_symbiosis2)[2]))

ci_sa_random_symbiosis1 <- confint(sa_random_symbiosis1)
ci_sa_random_symbiosis2 <- confint(sa_random_symbiosis2)
res_sa_random_symbiosis %<>% mutate(lowerCL = c(ci_sa_random_symbiosis1[3:4, 
    1], ci_sa_random_symbiosis2[4, 1]))
res_sa_random_symbiosis %<>% mutate(upperCL = c(ci_sa_random_symbiosis1[3:4, 
    2], ci_sa_random_symbiosis2[4, 2]))

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiosis1$name), cont_gen(res_symbiosis1$name)), 
    Estimate = res_sa_random_symbiosis$estiamte, `Lower CI [0.025]` = res_sa_random_symbiosis$lowerCL, 
    `Upper CI  [0.975]` = res_sa_random_symbiosis$upperCL, `V[authors]` = c(attr(VarCorr(sa_random_symbiosis1)$author, 
        "stddev")^2, rep(NA, 2)), `V[residuals]` = c(attr(VarCorr(sa_random_symbiosis1), 
        "sc")^2, rep(NA, 2)), R2 = c(r2_sa_random_symbiosis$R2_marginal, rep(NA, 
        2))) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] V[residuals] R2
Mutualist 7.696 7.286 8.106 2.931 0.352 0.004
Parasite 7.619 7.314 7.924 NA NA NA
Mutualist-Parasite -0.077 -0.544 0.389 NA NA NA

The effect of host taxa

# host_tax_broad mutiple intercepts
sa_random_host_tax_broad1 <- lmer(log(no_randomizations) ~ host_tax_broad - 
    1 + (1 | authors), data = dat)
# contrast 1
sa_random_host_tax_broad2 <- lmer(log(no_randomizations) ~ host_tax_broad + 
    (1 | authors), data = dat)
# contrast 2
sa_random_host_tax_broad3 <- lmer(log(no_randomizations) ~ relevel(host_tax_broad, 
    ref = "Plant") + (1 | authors), data = dat)

# contrast 3
sa_random_host_tax_broad4 <- lmer(log(no_randomizations) ~ relevel(host_tax_broad, 
    ref = "Invert") + (1 | authors), data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_sa_random_host_tax_broad <- r2_nakagawa(sa_random_host_tax_broad1)

# getting estimates
res_sa_random_host_tax_broad <- tibble(estiamte = c(fixef(sa_random_host_tax_broad1), 
                                                    fixef(sa_random_host_tax_broad2)[2:4],
                                                    fixef(sa_random_host_tax_broad3)[3:4],
                                                    fixef(sa_random_host_tax_broad4)[4])) 
  
ci_sa_random_host_tax_broad1<-confint(sa_random_host_tax_broad1)
ci_sa_random_host_tax_broad2<-confint(sa_random_host_tax_broad2)
ci_sa_random_host_tax_broad3<-confint(sa_random_host_tax_broad3)
ci_sa_random_host_tax_broad4<-confint(sa_random_host_tax_broad4)
res_sa_random_host_tax_broad %<>% mutate(lowerCL = c(ci_sa_random_host_tax_broad1[3:6,1], 
                                                ci_sa_random_host_tax_broad2[4:6,1],
                                                ci_sa_random_host_tax_broad3[5:6,1],
                                                ci_sa_random_host_tax_broad4[6,1]))
res_sa_random_host_tax_broad %<>% mutate(upperCL = c(ci_sa_random_host_tax_broad1[3:6,2], 
                                                ci_sa_random_host_tax_broad2[4:6,2],
                                                ci_sa_random_host_tax_broad3[5:6,2],
                                                ci_sa_random_host_tax_broad4[6,2]))
# creating a table
tibble(
  `Fixed effect` =  c(as.character(res_symbiont_tax_broad1$name), cont_gen(res_symbiont_tax_broad1$name)), # done
  Estimate = res_sa_random_host_tax_broad$estiamte,
  `Lower CI [0.025]` = res_sa_random_host_tax_broad$lowerCL,
  `Upper CI  [0.975]` = res_sa_random_host_tax_broad$upperCL,
  `V[authors]` = c(attr(VarCorr(sa_random_host_tax_broad1)$author,"stddev")^2,  rep(NA, 9)),
  `V[residuals]` =c(attr(VarCorr(sa_random_host_tax_broad1),"sc")^2, rep(NA, 9)),
  `R2` = c(r2_sa_random_host_tax_broad$R2_marginal, rep(NA, 9))) %>% kable("html", digits = 3) %>%
  kable_styling("striped", position = "left") 
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] V[residuals] R2
Microbe 8.223 7.279 9.168 2.937 0.35 0.071
Plant 7.466 6.856 8.076 NA NA NA
Invert 7.650 7.167 8.134 NA NA NA
Vert 7.634 7.265 8.003 NA NA NA
Microbe-Plant -0.757 -1.882 0.367 NA NA NA
Microbe-Invert -0.573 -1.634 0.488 NA NA NA
Microbe-Vert -0.589 -1.603 0.425 NA NA NA
Plant-Invert 0.184 -0.594 0.962 NA NA NA
Plant-Vert 0.168 -0.545 0.881 NA NA NA
Invert-Vert -0.016 -0.599 0.566 NA NA NA

The effect of the model of transmission

# mode_of_transmission_broad

sa_random_mode_of_transmission_broad1 <- lmer(log(no_randomizations) ~ mode_of_transmission_broad - 
    1 + (1 | authors), data = dat)


# contrast 1
sa_random_mode_of_transmission_broad2 <- lmer(log(no_randomizations) ~ mode_of_transmission_broad + 
    (1 | authors), data = dat)

# contrast 2
sa_random_mode_of_transmission_broad3 <- lmer(log(no_randomizations) ~ relevel(mode_of_transmission_broad, 
    ref = "vertical") + (1 | authors), data = dat)

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# getting marginal R2
r2_sa_random_mode_of_transmission_broad <- r2_nakagawa(sa_random_mode_of_transmission_broad1)

# getting estimates
res_sa_random_mode_of_transmission_broad <- tibble(estiamte = c(fixef(sa_random_mode_of_transmission_broad1), 
    fixef(sa_random_mode_of_transmission_broad2)[2:3], fixef(sa_random_mode_of_transmission_broad3)[3]))

ci_sa_random_mode_of_transmission_broad1 <- confint(sa_random_mode_of_transmission_broad1)
ci_sa_random_mode_of_transmission_broad2 <- confint(sa_random_mode_of_transmission_broad2)
ci_sa_random_mode_of_transmission_broad3 <- confint(sa_random_mode_of_transmission_broad3)
res_sa_random_mode_of_transmission_broad %<>% mutate(lowerCL = c(ci_sa_random_mode_of_transmission_broad1[3:5, 
    1], ci_sa_random_mode_of_transmission_broad2[4:5, 1], ci_sa_random_mode_of_transmission_broad3[5, 
    1]))
res_sa_random_mode_of_transmission_broad %<>% mutate(upperCL = c(ci_sa_random_mode_of_transmission_broad1[3:5, 
    2], ci_sa_random_mode_of_transmission_broad2[4:5, 2], ci_sa_random_mode_of_transmission_broad3[5, 
    2]))
# creating a table
tibble(`Fixed effect` = c(as.character(res_mode_of_transmission_broad1$name), 
    cont_gen(res_mode_of_transmission_broad1$name)), Estimate = res_sa_random_mode_of_transmission_broad$estiamte, 
    `Lower CI [0.025]` = res_sa_random_mode_of_transmission_broad$lowerCL, `Upper CI  [0.975]` = res_sa_random_mode_of_transmission_broad$upperCL, 
    `V[authors]` = c(attr(VarCorr(sa_random_mode_of_transmission_broad1)$author, 
        "stddev")^2, rep(NA, 5)), `V[residuals]` = c(attr(VarCorr(sa_random_mode_of_transmission_broad1), 
        "sc")^2, rep(NA, 5)), R2 = c(r2_sa_random_mode_of_transmission_broad$R2_marginal, 
        rep(NA, 5))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] V[residuals] R2
both 7.535 6.978 8.091 2.913 0.363 0.12
horizontal 7.515 7.164 7.866 NA NA NA
vertical 8.089 7.509 8.668 NA NA NA
both-horizontal -0.020 -0.678 0.638 NA NA NA
both-vertical 0.554 -0.250 1.357 NA NA NA
horizontal-vertical -0.574 -1.251 0.104 NA NA NA

Sensitivity test 2: reaching the limits

The type of symbiosis: parasitism vs. mutualism

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# symbiosis
sa_limit_symbiosis1 <- glmer(limit_rearched ~ symbiosis - 1 + (1 | authors), 
    family = "binomial", data = dat)

# getting marginal R2
r2_sa_limit_symbiosis <- r2_nakagawa(sa_limit_symbiosis1)

# getting estimates
res_sa_limit_symbiosis <- tibble(estiamte = fixef(sa_limit_symbiosis1))

res_sa_limit_symbiosis %<>% mutate(lowerCL = (tidy(sa_limit_symbiosis1)$estimate[-3] - 
    tidy(sa_limit_symbiosis1)$std.error[-3] * qnorm(0.975)))
res_sa_limit_symbiosis %<>% mutate(upperCL = (tidy(sa_limit_symbiosis1)$estimate[-3] + 
    tidy(sa_limit_symbiosis1)$std.error[-3] * qnorm(0.975)))
# creating a table
tibble(`Fixed effect` = as.character(res_symbiosis1$name), Estimate = res_sa_limit_symbiosis$estiamte, 
    `Lower CI [0.025]` = res_sa_limit_symbiosis$lowerCL, `Upper CI  [0.975]` = res_sa_limit_symbiosis$upperCL, 
    `V[authors]` = c(attr(VarCorr(sa_limit_symbiosis1)$author, "stddev")^2, 
        rep(NA, 1)), R2 = c(r2_sa_limit_symbiosis$R2_marginal, rep(NA, 1))) %>% 
    kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Mutualist -0.401 -1.074 0.272 1.657 0.051
Parasite -1.309 -2.015 -0.603 NA NA

The effect of host taxa

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# host_tax_broad
sa_limit_host_tax_broad1 <- glmer(limit_rearched ~ host_tax_broad - 1 + (1 | 
    authors), family = "binomial", data = dat)

# getting marginal R2
r2_sa_limit_host_tax_broad <- r2_nakagawa(sa_limit_host_tax_broad1)

# getting estimates
res_sa_limit_host_tax_broad <- tibble(estiamte = fixef(sa_limit_host_tax_broad1))

res_sa_limit_host_tax_broad %<>% mutate(lowerCL = (tidy(sa_limit_host_tax_broad1)$estimate[-5] - 
    tidy(sa_limit_host_tax_broad1)$std.error[-5] * qnorm(0.975)))
res_sa_limit_host_tax_broad %<>% mutate(upperCL = (tidy(sa_limit_host_tax_broad1)$estimate[-5] + 
    tidy(sa_limit_host_tax_broad1)$std.error[-5] * qnorm(0.975)))
# creating a table
tibble(`Fixed effect` = as.character(res_symbiont_tax_broad1$name), Estimate = res_sa_limit_host_tax_broad$estiamte, 
    `Lower CI [0.025]` = res_sa_limit_host_tax_broad$lowerCL, `Upper CI  [0.975]` = res_sa_limit_host_tax_broad$upperCL, 
    `V[authors]` = c(attr(VarCorr(sa_limit_host_tax_broad1)$author, "stddev")^2, 
        rep(NA, 3)), R2 = c(r2_sa_limit_host_tax_broad$R2_marginal, rep(NA, 
        3))) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Microbe -1.211 -2.737 0.316 1.358 0.035
Plant -1.574 -2.571 -0.578 NA NA
Invert -0.579 -1.308 0.150 NA NA
Vert -0.937 -1.588 -0.286 NA NA

The effect of the model of transmission

Supplementary Table 3: Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance examplained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad.

# mode_of_transmission_broad
sa_limit_mode_of_transmission_broad1 <- glmer(limit_rearched ~ mode_of_transmission_broad - 
    1 + (1 | authors), family = "binomial", data = dat)

# getting marginal R2
r2_sa_limit_mode_of_transmission_broad <- r2_nakagawa(sa_limit_mode_of_transmission_broad1)

# getting estimates
res_sa_limit_mode_of_transmission_broad <- tibble(estiamte = fixef(sa_limit_mode_of_transmission_broad1))

res_sa_limit_mode_of_transmission_broad %<>% mutate(lowerCL = (tidy(sa_limit_mode_of_transmission_broad1)$estimate[-4] - 
    tidy(sa_limit_mode_of_transmission_broad1)$std.error[-4] * qnorm(0.975)))
res_sa_limit_mode_of_transmission_broad %<>% mutate(upperCL = (tidy(sa_limit_mode_of_transmission_broad1)$estimate[-4] + 
    tidy(sa_limit_mode_of_transmission_broad1)$std.error[-4] * qnorm(0.975)))
# creating a table
tibble(`Fixed effect` = as.character(res_mode_of_transmission_broad1$name), 
    Estimate = res_sa_limit_mode_of_transmission_broad$estiamte, `Lower CI [0.025]` = res_sa_limit_mode_of_transmission_broad$lowerCL, 
    `Upper CI  [0.975]` = res_sa_limit_mode_of_transmission_broad$upperCL, `V[authors]` = c(attr(VarCorr(sa_limit_mode_of_transmission_broad1)$author, 
        "stddev")^2, rep(NA, 2)), R2 = c(r2_sa_limit_mode_of_transmission_broad$R2_marginal, 
        rep(NA, 2))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
both -0.928 -1.809 -0.046 1.427 0.078
horizontal -1.326 -2.031 -0.621 NA NA
vertical 0.060 -0.750 0.869 NA NA

Recommendation

  • they need to run more simuations so they do not max out!
  • reanalysis of earlier trees are necessary; getting older or updated trees are required
  • new studies should provide all data avaiable online so that future analysis can incorprate all avaiable data

Acknowledgement

Much of coding materials have been borrowed from h

Refererences

Information for this R session

sessionInfo() %>% pander()

R version 3.6.0 (2019-04-26)

Platform: x86_64-apple-darwin15.6.0 (64-bit)

locale: en_AU.UTF-8||en_AU.UTF-8||en_AU.UTF-8||C||en_AU.UTF-8||en_AU.UTF-8

attached base packages: stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: lmerTest(v.3.1-0), performance(v.0.2.0), broom.mixed(v.0.2.4), lme4(v.1.1-21), MuMIn(v.1.43.6), plotly(v.4.9.0), ggbeeswarm(v.0.6.0), MCMCglmm(v.2.29), ape(v.5.3), coda(v.0.19-3), metafor(v.2.1-0), Matrix(v.1.2-17), pander(v.0.6.3), magrittr(v.1.5), gridExtra(v.2.3), kableExtra(v.1.1.0), forcats(v.0.4.0), stringr(v.1.4.0), dplyr(v.0.8.1), purrr(v.0.3.2), readr(v.1.3.1), tidyr(v.0.8.3), tibble(v.2.1.3), ggplot2(v.3.2.0) and tidyverse(v.1.2.1)

loaded via a namespace (and not attached): httr(v.1.4.0), jsonlite(v.1.6), viridisLite(v.0.3.0), splines(v.3.6.0), modelr(v.0.1.4), assertthat(v.0.2.1), highr(v.0.8), stats4(v.3.6.0), tensorA(v.0.36.1), vipor(v.0.4.5), cellranger(v.1.1.0), bayestestR(v.0.2.2), yaml(v.2.2.0), numDeriv(v.2016.8-1.1), pillar(v.1.4.2), backports(v.1.1.4), lattice(v.0.20-38), glue(v.1.3.1), digest(v.0.6.20), rvest(v.0.3.4), minqa(v.1.2.4), colorspace(v.1.4-1), htmltools(v.0.3.6), plyr(v.1.8.4), pkgconfig(v.2.0.2), broom(v.0.5.2), haven(v.2.1.0), corpcor(v.1.6.9), scales(v.1.0.0), webshot(v.0.5.1), cubature(v.2.0.3), generics(v.0.0.2), withr(v.2.1.2), TMB(v.1.7.15), lazyeval(v.0.2.2), cli(v.1.1.0), crayon(v.1.3.4), readxl(v.1.3.1), evaluate(v.0.14), nlme(v.3.1-140), MASS(v.7.3-51.4), xml2(v.1.2.0), beeswarm(v.0.2.3), tools(v.3.6.0), data.table(v.1.12.2), hms(v.0.4.2), formatR(v.1.6), munsell(v.0.5.0), compiler(v.3.6.0), rlang(v.0.4.0), grid(v.3.6.0), nloptr(v.1.2.1), rstudioapi(v.0.10.0-9000), htmlwidgets(v.1.3), labeling(v.0.3), base64enc(v.0.1-3), rmarkdown(v.1.13), boot(v.1.3-22), codetools(v.0.2-16), gtable(v.0.3.0), reshape2(v.1.4.3), R6(v.2.4.0), lubridate(v.1.7.4), knitr(v.1.23), insight(v.0.4.1), stringi(v.1.4.3), parallel(v.3.6.0), Rcpp(v.1.0.2), tidyselect(v.0.2.5) and xfun(v.0.7)

LS0tCnRpdGxlOiAiVGVzdGluZyB0aGUgZ2VuZXJhbGl0eSBvZiBob3N0LXN5bWJpb250IGNvcGh5bG9nZW55IgphdXRob3I6ICJBbGV4YW5kZXIgSGF5d2FyZCwgUm9iZXJ0IFBvdWxpbiAmIFNoaW5pY2hpIE5ha2FnYXdhIgpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiAlWScpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGRlcHRoOiA1CiAgICBudW1iZXJfc2VjdGlvbnM6IG5vCiAgICB0aGVtZTogIGNvc21vICMg4oCcZGVmYXVsdOKAnSwg4oCcY2VydWxlYW7igJ0sIOKAnGpvdXJuYWzigJ0sIOKAnGZsYXRseeKAnSwg4oCcZGFya2x54oCdLCDigJxyZWFkYWJsZeKAnSwg4oCcc3BhY2VsYWLigJ0sIOKAnHVuaXRlZOKAnSwg4oCcY29zbW/igJ0sIOKAnGx1bWVu4oCdLCDigJxwYXBlcuKAnSwg4oCcc2FuZHN0b25l4oCdLCDigJxzaW1wbGV44oCdLCDigJx5ZXRp4oCdCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwpzdWJ0aXRsZTogRWxlY3Ryb25pYyBTdXBwbGVtZW50YXJ5IE1hdGVyaWFsCmJpYmxpb2dyYXBoeTogcmVmZXJlbmNlcy5iaWIKLS0tCgo8IS0tLSBUcnkgdG8gYWRkIHJlZmVyZW5jZXMgZm9yIHRoaXMhISEhIC0tLT4KCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0V9CiNrbml0ZXIgc2VldHRpbmcKa25pdHI6Om9wdHNfY2h1bmskc2V0KAptZXNzYWdlID0gRkFMU0UsCndhcm5pbmcgPSBGQUxTRSwgIyBubyB3YXJuaW5ncwpjYWNoZSA9IFRSVUUsIyBDYWNoZWluZyB0byBzYXZlIHRpbWUgd2hlbiBrbml0aW5nCnRpZHkgPSBUUlVFCiNmaWcud2lkdGggPSA5CikKCiMgY2xlYXJuaW5nIHVwCnJtKGxpc3Q9bHMoKSkKYGBgCgojIyBTZXR1cHMKCiMjIyBMb2FkaW5nIHBhY2FrZ2VzIGFuZCBjdXN0dW0gZnVuY3Rpb25zCgpgYGB7cn0KIyBsb2FkaW5nIHBhY2thZ2VzCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSwgIyB0aWR5IGZhbWlseSBhbmQgcmVsYXRlZCBwYWNha2dlcyBiZWxvdwogICAgICAgICAgICAgICBrYWJsZUV4dHJhLCAKICAgICAgICAgICAgICAgZ3JpZEV4dHJhLCAKICAgICAgICAgICAgICAgcHVycnIsCiAgICAgICAgICAgICAgIG1hZ3JpdHRyLCAjIGV4dGVuZGluZyBwaXBpbmcKICAgICAgICAgICAgICAgcGFuZGVyLCAgICMgbmljZSB0YWJsZXMKICAgICAgICAgICAgICAgbWV0YWZvciwgICMgcGFja2FnZSBmb3IgbWV0YS1hbmFseXNpcwogICAgICAgICAgICAgICBNQ01DZ2xtbSwgICMgQmF5ZWlzYW4gbWl4ZWQgbW9kZWwgcGFja2FnZQogICAgICAgICAgICAgICBnZ2JlZXN3YXJtLCAjIG1ha2luZyBiZWUtc3dhcm0gcGxvdHMgcG9zc2libGUKICAgICAgICAgICAgICAgcGxvdGx5LCAgICAgIyBpbnRlcmFjdGl2ZSBwbG90cyB1c2luZyBnZ3Bsb3QyCiAgICAgICAgICAgICAgIE11TUluLCAgIyBtdWx0aS1tb2RlbCBpbmZlcmVuY2UKICAgICAgICAgICAgICAgbG1lNCwgICAjIGxtbSAmIGdsbW0gKG1vZGVscykKICAgICAgICAgICAgICAgYnJvb20ubWl4ZWQsICMgZ2V0dGluZyBlc3RpbWF0ZXMgZnJvbSBsbWVyICsgZ2xtZXIgb2JqZWN0cwogICAgICAgICAgICAgICBwZXJmb3JtYW5jZSwgIyBnZXR0aW5nIFIyIGZyb20gbG1lciArIGdsbWVyIG9iamVjdHMKICAgICAgICAgICAgICAgI2xtZXJUZXN0CiAgICAgICAgICAgICAgICNtaSwgICAgICAjIG1pc3NpbmcgZGF0YSBhbmFseXNpcwogICAgICAgICAgICAgICAjYmV0YXJlZyAgICMgZGVwZW5kYW5jZSBvZiB0aGUgYWJvdmUKKQoKIyBnZXR0aW5nIGZ1bmN0aW9ucyAKc291cmNlKCIuLi9SL0VTTV9mdW5jdGlvbnMuUiIsIGNoZGlyID0gVFJVRSkKCmBgYAoKIyMjIyBDdXN0dW0gZnVuY3Rpb25zCgpOT1RFISEhCldlIGhhdmUgWFggY3VzdHVtIGZ1bmN0aW9uczogLi4uLi4uLiAKCiMjIFN1cHBsZW1lbnRhcnkgTWV0aG9kcyBhbmQgTWF0ZXJpYWxzCgojIyMgWFhYWDEKCiMjIyBYWFhYMgoKIyMgVGhlIENvcGh5bG9nZW55IERhdGFzZXQKCiMjIyBUYWJsZSBvZiB0aGUgZGF0YXNldAoKQmVsb3cgaXMgdGhlIGRhdGFzZXQgdXNlZCBmb3Igb3VyIG1ldGEtYW5hbHlzaXMgZm9sbHdlZCBieSBleHBsYW5hdGlvbnMgb2YgMjQgdmFyaWFibGVzIG9yaWdpbmFsIGNvbGxlY3RlZCAobm90IGFsbCB2YXJhaWJsZXMgd2VyZSB1c2VkIGZvciBvdXIgYW5hbHlzZXM7IHZhcmlhYmxlcyB3aGljaCB3ZXJlIG5laXRoZXIgJ2RpcmVjdGx5JyBub3IgJ2luZGlyZWN0bHknIHVzZWQgaW4gb3VyIGFuYWx5c2VzIGFyZSBpbmRpY2F0ZWQgYnkgKikKCmBgYHtyfQojIGdldHRpbmcgdGhlIGRhdGEgYW5kIGZvcm1hdGluZyBzb21lIHZhcmlhYmxlcyAodHVybmluZyBjaHJhcmFjdGVyIHZlY3RvcnMgdG8gZmFjdG9ycykKIyByZWFkIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gZmFjdHIoKSBhbmQgYXMuZmFjdG9yKCkgPGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM5Mjc5MjM4L3doeS11c2UtYXMtZmFjdG9yLWluc3RlYWQtb2YtanVzdC1mYWN0b3I+CiMgZnVsbF9kYXRhIDwtIHJlYWQuY3N2KCIuLi9kYXRhLzIwMTktMDQtMDQtc291cmNlLWRhdGEtZGF0LmNzdiIsIG5hID0gIk5BIiwgZmlsZUVuY29kaW5nPSJVVEYtOCIpICU+JQojICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCBhcy5mYWN0b3IpCmZ1bGxfZGF0YSA8LSByZWFkX2NzdigiLi4vZGF0YS8yMDE5LTIzLTA3LXNvdXJjZS1kYXRhLWRhdC5jc3YiLCBuYSA9ICJOQSIpICU+JSAKICAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMuZmFjdG9yKQoKIyBtYWtpbmcgYSBzY3JvbGxhYmxlIHRhYmxlCmthYmxlKGZ1bGxfZGF0YSwgImh0bWwiKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICI1MDBweCIpCmBgYAoKQS4gX19hdXRob3JzX186IFRoZSBhdXRob3JzIG9mIHRoZSBzdHVkeSBhbmQgdGhlIGRhdGUgKGNpdGF0aW9uIGZvcm0pLgoKQi4gX195ZWFyX186IFllYXIgb2YgcHVibGljYXRpb24gb2YgdGhlIHN0dWR5LgoKQy4gX19ob3N0X3RheF9icm9hZF9fOglTZXBhcmF0aW9uIG9mIHRoZSBob3N0IGdyb3VwIGFjY29yZGluZyB0byBicm9hZGVyIHRheG9ub21pYyB1bml0cyAoZS5nLiB2ZXJ0ZWJyYXRlLCBpbnZlcnRlYnJhdGUsIG1pY3JvYmUsIHBsYW50KS4KCkQuIF9faG9zdF90YXhfZmluZV9fKjoJU2VwYXJhdGlvbiBvZiB0aGUgaG9zdCBncm91cCBhY2NvcmRpbmcgdG8gbmFycm93ZXIgdGF4b25vbWljIHVuaXRzIChlLmcuIGZpc2gsIHRldHJhcG9kLCBiaXJkLCBpbnZlcnRlYnJhdGUsIHByb3Rpc3QsIGJhY3Rlcml1bSwgcGxhbnQsIGZ1bmd1cykuCgpFLiBfX3N5bWJpb250X3RheF9icm9hZF9fOglTZXBhcmF0aW9uIG9mIHRoZSBzeW1iaW9udCBncm91cCBhY2NvcmRpbmcgdG8gYnJvYWRlciB0YXhvbm9taWMgdW5pdHMgKGUuZy4gdmVydGVicmF0ZSwgaW52ZXJ0ZWJyYXRlLCBtaWNyb2JlLCBwbGFudCkuCgpGLiBfX3N5bWJpb250X3RheF9maW5lX18qOglTZXBhcmF0aW9uIG9mIHRoZSBzeW1iaW9udCBncm91cCBhY2NvcmRpbmcgdG8gbmFycm93ZXIgdGF4b25vbWljIHVuaXRzIChlLmcuIGludmVydGVicmF0ZSwgcHJvdGlzdCwgdmlydXMsIGJhY3Rlcml1bSwgZnVuZ3VzLCBwbGFudCwgYmlyZCkuCgpHLiBfX3N5bWJpb250X2V1a19fKjoJV2hldGhlciB0aGUgc3ltYmlvbnQgaXMgZXVrYXJ5b3RpYyAoc3RhdGUgPSd5ZXMnKSwgb3IgcHJva2FyeW90aWMgKHN0YXRlPSdubycpLgoKSC4gX19zeW1iaW9zaXNfXzoJVGhlIHR5cGUgb2Ygc3ltYmlvbnQgKGUuZy4gcGFyYXNpdGUgb3IgbXV0dWFsaXN0KS4gRm9yIHRoaXMgd2UgZm9sbG93ZWQgdGhlIGRlZmluaXRpb24gdXNlZCBieSB0aGUgYXV0aG9ycyBvZiB0aGUgc3R1ZHkuCgpJLiBfX2VuZG9fb3JfZWN0b19fOglXaGV0aGVyIHRoZSBzeW1iaW9udCBsaXZlcyBvdXRzaWRlIHRoZSBob3N0IChpLmUuIGlzIGFuIGVjdG9zeW1iaW9udCksIG9yIGluc2lkZSB0aGUgaG9zdCAoaS5lLiBpcyBhbiBlbmRvc3ltYmlvbnQpLgoKSi4gX19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZF9fOglXaGV0aGVyIHRoZSBzeW1iaW9udCBpcyB0cmFuc21pdHRlZCB2ZXJ0aWNhbGx5LCBob3Jpem9udGFsbHksIG9yIGJvdGguIEZvciB0aGlzLCB3ZSBmb2xsb3dlZCB0aGUgcm91dGUgb2YgdHJhbnNtaXNzaW9uIHNwZWNpZmllZCBieSB0aGUgYXV0aG9ycyBvZiB0aGUgc3R1ZHkKCksuIF9fbW9kZV9vZl90cmFuc21pc3Npb25fZmluZV9fKjoJQSBmaW5lci1zY2FsZSBkZXNjcmlwdGlvbiBvZiB0aGUgbW9kZSBvZiB0cmFuc21pc3Npb24gb2YgdGhlIHN5bWJpb250IChlLmcuIGNvbnRhY3QsIHZlY3RvciwgYm9kaWx5IGZsdWlkLCB2ZXJ0aWNhbCwgdHJvcGhpYykuCgpMLiBfX3N5bWJpb250X18qOglTaG9ydGhhbmQgZGVzY3JpcHRpb24gb2YgdGhlIHR5cGUgb2Ygc3ltYmlvbnQuCgpNLiBfX1Zpc2l0aW5nX3N5bWJpb250P19fKglXaGV0aGVyIHRoZSBzeW1iaW9udCBpcyByZXNpZGVudCBvbiB0aGUgaG9zdCAocmVzaWRlbnQpLCBvciBtYWtlcyB2aXNpdHMgdG8gdGhlIGhvc3Qgb3IgaG9zdHMgKHZpc2l0b3IpLgoKTi4gX19ob3N0X3RpcHNfbGlua2VkX186CVRoZSBudW1iZXIgb2YgaW5kaXZpZHVhbCBob3N0IHRheGEgaW5jbHVkZWQgaW4gdGhlIGNvcGh5bG9nZW5ldGljIGFuYWx5c2lzLgoKTy4gX19ob3N0X3RpcHNfbGlua2VkX2NvcnJlY3RlZF9fCVRoZSBzYW1lIG1lYXN1cmUgYXMgZm9yIGNvbHVtbiBOLCAnaG9zdF90aXBzX2xpbmtlZCcsIGJ1dCByZWR1Y2VkIHRvIG9ubHkgaW5jbHVkZSBvbmUgbWVtYmVyIG9mIGVhY2ggaG9zdCBzcGVjaWVzLiBUaGlzIGlzIGluY2x1ZGVkIGJlY2F1c2Ugc29tZSBhdXRob3JzIGluY2x1ZGUgbXVsdGlwbGUgaW5kaXZpZHVhbHMgb2YgdGhlIHNhbWUgaG9zdCBzcGVjaWVzLiBXaXRob3V0IGNvcnJlY3Rpb24sIHRoaXMgYXJ0aWZpY2lhbGx5IGluY3JlYXNlcyB0aGUgYXBwYXJlbnQgbnVtYmVyIG9mIGhvc3Qgc3BlY2llcyBpbmNsdWRlZCBpbiB0aGUgc3R1ZHkuCgpQLiBfX2hvc3RfZ2VuZXJhX186CUEgY291bnQgb2YgdGhlIG51bWJlciBvZiBob3N0IGdlbmVyYSBpbmNsdWRlZCBpbiB0aGUgY29waHlsb2dlbmV0aWMgYW5hbHlzaXMKClEuIF9fdG90YWxfaG9zdF9zeW1iaW9pbnRfbGlua3NfXwlUaGUgdG90YWwgbnVtYmVyIG9mIGxpbmtzIGJldHdlZW4gaG9zdCBhbmQgc3ltYmlvbnQgdGF4YSByZWNvcmRlZCBpbiBhIHN0dWR5LiBJZiBhbGwgc3ltYmlvbnRzIHdlcmUgc3RyaWN0IHNwZWNpYWxpc3RzLCB0aGlzIHdvdWxkIGVxdWFsIHRoZSBudW1iZXIgb2Ygc3ltYmlvbnRzIGluY2x1ZGVkIGluIHRoZSBzdHVkeS4gSG93ZXZlciwgYmVjYXVzZSBzeW1iaW9udHMgYXJlIG9mdGVuIGFzc29jaWF0ZWQgd2l0aCBtb3JlIHRoYW4gb25lIGhvc3QsIHRoaXMgdmFsdWUgaXMgb2Z0ZW4gaGlnaGVyIHRoYW4gdGhlIHRvdGFsIG51bWJlciBvZiBzeW1iaW9udHMgaW5jbHVkZWQgaW4gdGhlIHN0dWR5LgoKUi4gX19ob3N0X3JhbmdlX2xpbmtfcmF0aW9fXzoJQW4gZXN0aW1hdGlvbiBvZiBzeW1iaW9udCBob3N0IHNwZWNpZmljaXR5LCBjYWxjdWxhdGVkIGJ5IGRpdmlkaW5nIHRoZSB0b3RhbCBudW1iZXIgb2YgbGlua3MgYmV0d2VlbiBob3N0cyBhbmQgc3ltYmlvbnRzIChpLmUuICd0b3RhbF9ob3N0X3N5bWJpb250X2xpbmtzJywgY29sdW1uIFEpLCBieSB0aGUgdG90YWwgbnVtYmVyIG9mIHN5bWJpb250cyBpbmNsdWRlZCBpbiB0aGUgc3R1ZHkgKGkuZS4gJ3N5bWJpb250X3RpcHNfbGlua2VkJywgY29sdW1uIFQpLgoKUy4gX19ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoX186CUFuIGFsdGVybmF0aXZlIGVzdGltYXRpb24gb2Ygc3ltYmlvbnQgaG9zdCBzcGVjaWZpY2l0eSwgY2FsY3VsYXRlZCBieSBmaXJzdCBzdW1taW5nIHRoZSBudW1iZXIgb2YgaG9zdCB0YXhvbm9taWMgcmFua3MgbGlua2VkIHRvIGVhY2ggc3ltYmlvbnQgKGkuZS4gc2luZ2xlIGhvc3Qgc3BlY2llcyA9IDEsIG11bHRpcGxlIGhvc3Qgc3BlY2llcyBpbiB0aGUgc2FtZSBnZW5lcmEgPSAyLCBtdWx0aXBsZSBob3N0IGdlbmVyYSA9IDMsIG11bHRpcGxlIGhvc3QgZmFtaWxlcyA9IDQsIG11bHRpcGxlIGhvc3Qgb3JkZXJzID0gNSksIGFuZCBkaXZpZGluZyBieSB0aGUgdG90YWwgbnVtYmVyIG9mIHN5bWJpb250cyBpbmNsdWRlZCBpbiB0aGUgc3R1ZHkgKGkuZS4gJ3N5bWJpb250X3RpcHNfbGlua2VkJywgY29sdW1uIFQpCgpULiBfX3N5bWJpb250X3RpcHNfbGlua2VkX18JVGhlIG51bWJlciBvZiBpbmRpdmlkdWFsIHN5bWJpb250IHRheGEgaW5jbHVkZWQgaW4gdGhlIGNvcGh5bG9nZW5ldGljIGFuYWx5c2lzLgoKVS4gX19zeW1iaW9udF9nZW5lcmFfXzoJQSBjb3VudCBvZiB0aGUgbnVtYmVyIG9mIHN5bWJpb250IGdlbmVyYSBpbmNsdWRlZCBpbiB0aGUgY29waHlsb2dlbmV0aWMgYW5hbHlzaXMuCgpWLiBfX25vX3JhbmRvbWl6YXRpb25zX186CVRoZSBudW1iZXIgb2YgcGh5bG9nZW5ldGljIHJhbmRvbWl6YXRpb25zIHBlcmZvcm1lZCBkdXJpbmcgdGhlIGNvcGh5bG9nZW5ldGljIGFuYWx5c2lzLgoKVy4gX19wX3ZhbHVlX186CVRoZSBwLXZhbHVlIHJlcG9ydGVkIGZvciB0aGUgY29waHlsb2dlbmV0aWMgYW5hbHlzaXMsIHJlcHJlc2VudGluZyB0aGUgbGlrZWxpaG9vZCB0aGF0IGhvc3QgYW5kIHN5bWJ0aW9uIHBoeWxvZ2VuaWVzIGRpc3BsYXkgY29zcGVjaWF0aW9uLgoKWC4gX19tZXRob2RfXzoJV2hldGhlciBUcmVlTWFwIG9yIFBhcmFmaXQgd2FzIHVzZWQgdG8gb2J0YWluIGNvLWRpdmVyZ2VuY2Ugb3IgYSBwIHZhbHVlLgoKIyMjIFRhYmxlIG9mIHNhbXBsZSBzaXplcwoKV2UgcHJlc2VudCB0aGUgbnVtYmVyIG9mIHNhbXBsZSBzaXplIGZvciB0d28gc2VwcmVhdGUgbWV0aG9kczogVHJlZU1hcCBhbmQgUGFyYWZpdCAoYW5kIGNvbWJpbmVkKSBmb3IgZWZmZWN0IHNpemVzLCBwYXBlcnMgYW5kIGRpZmZlcmVudCBsZXZlbHMgb2YgY2F0ZWdvcmljYWwgdmFyYWlibGVzIChmYWN0b3JzKS4gICAKCmBgYHtyfQojIHNlbGVjdGluZyBvdXQgdmFyaWFibGVzLCB3aGljaCB3ZSB1c2VkIGZvciBvdXIgYW5hbHlzaXMKZGF0IDwtIGZ1bGxfZGF0YSAlPiUgc2VsZWN0KC1ob3N0X3RheF9maW5lLCAtc3ltYmlvbnRfdGF4X2ZpbmUsIC1zeW1iaW9udF9ldWssIC1tb2RlX29mX3RyYW5zbWlzc2lvbl9maW5lLCAtc3ltYmlvbnQsIC1gVmlzaXRpbmdfc3ltYmlvbnQ/YCkKCiMgbWFraW5nIGEgdGFibGUgb2Ygc2FtcGxlIHNpemVzIGZvciBkaWZmZXJlbnQgdmFyaWFibGVzCmRhdCAlPiUgZ3JvdXBfYnkobWV0aG9kKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgYEVmZmVjdCBzaXplc2AgPSBuKCksCiAgICBQYXBlcnMgPSBuX2Rpc3RpbmN0KGF1dGhvcnMpLAogICAgYFZlcnRlYnJhdGUgaG9zdHNgID0gc3VtKGhvc3RfdGF4X2Jyb2FkID09ICJWZXJ0IiwgbmEucm0gPSBUKSwgIyBuYS5ybSBpcyBpbXBvcnRhbnQgd2hlbiBOQSBleGlzdHMKICAgIGBJbnZlcnRlYnJhdGUgaG9zdHNgID0gc3VtKGhvc3RfdGF4X2Jyb2FkID09ICJJbnZlcnQiLCBuYS5ybSA9IFQpLAogICAgYFBsYW50IGhvc3RzYCAgPSBzdW0oaG9zdF90YXhfYnJvYWQgPT0gIlBsYW50IiwgbmEucm0gPSBUKSwKICAgIGBNaWNyb2JlIGhvc3RzYCA9IHN1bShob3N0X3RheF9icm9hZCA9PSAiTWljcm9iZSIsIG5hLnJtID0gVCksCiAgICBgVmVydGVicmF0ZSBzeW1iaW9udHNgID0gc3VtKHN5bWJpb250X3RheF9icm9hZCAgPT0gIlZlcnQiLCBuYS5ybSA9IFQpLAogICAgYEludmVydGVicmF0ZSBzeW1iaW9udHNgID0gc3VtKHN5bWJpb250X3RheF9icm9hZCAgPT0gIkludmVydCIsIG5hLnJtID0gVCksCiAgICBgUGxhbnQgc3ltYmlvbnRzYCAgPSBzdW0oc3ltYmlvbnRfdGF4X2Jyb2FkICA9PSAiUGxhbnQiLCBuYS5ybSA9IFQpLAogICAgYE1pY3JvYmUgc3ltYmlvbnRzYCA9IHN1bShzeW1iaW9udF90YXhfYnJvYWQgID09ICJNaWNyb2JlIiwgbmEucm0gPSBUKSwKICAgIGBQYXJhc3RpYyByZWxhdGlvbnNoaXBzYCA9IHN1bShzeW1iaW9zaXMgPT0gIlBhcmFzaXRlIiwgbmEucm0gPSBUKSwKICAgIGBNdXR1YWxpc3RpYyByZWxhdGlvc2hpcHNgID0gc3VtKHN5bWJpb3NpcyA9PSAiTXV0dWFsaXN0IiwgbmEucm0gPSBUKSwKICAgIGBFY3RvLXN5bWJpb250c2AgPSBzdW0oZW5kb19vcl9lY3RvICA9PSAiRWN0byIsIG5hLnJtID0gVCksCiAgICBgRW5kby1zeW1iaW9udHNgID0gc3VtKGVuZG9fb3JfZWN0byA9PSAiRW5kbyIsIG5hLnJtID0gVCksCiAgICBgRWN0by9lbmRvLXN5bWJpb250c2AgPSBzdW0oZW5kb19vcl9lY3RvID09ICJFbmRvL0VjdG8iLCBuYS5ybSA9IFQpLAogICAgYEhvcml6b250YWwgdHJhbnNtaXNzaW9uYCA9IHN1bShtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCAgPT0gImhvcml6b250YWwiLCBuYS5ybSA9IFQpLAogICAgYFZlcnRpY2FsIHRyYW5zbWlzc2lvbmAgPSBzdW0obW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPT0gInZlcnRpY2FsIiwgbmEucm0gPSBUKSwKICAgIGBIb3Jpem9udGFsL3ZlcnRpY2FsLXRyYW5zbWlzc2lvbmAgPSBzdW0obW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPT0gImJvdGgiLCBuYS5ybSA9IFQpCiAgKSAtPiBuX3RhYmxlMQoKIyB0cmFuc3Bvc2luZyB0aGUgdGFibGUgYW5kIGNyZWF0aW5nIHRoYXQgdGFibGUgYW5kIGFkZGluZyBhIGNvcnJlY3QgbnVtYmVyIG9mIHRoZSBwYXBlcnMgZm9yIGBDb21iaW5lZGAKbl9hdXRob3JzIDwtIG5fZGlzdGluY3QoZGF0JGF1dGhvcnMpICMgdGhlIHRvdGFsIG51bWJlciBvZiBwYXBlcnMKbl90YWJsZTIgPC10KG5fdGFibGUxWywtMV0pCmNvbG5hbWVzKG5fdGFibGUyKSA8LSBuX3RhYmxlMSRtZXRob2QKbl90YWJsZTIgJT4lIGFzX3RpYmJsZShyb3duYW1lcyA9ICJOdW1iZXIiKSAlPiUgCiAgbXV0YXRlKENvbWJpbmVkID0gUGFyYWZpdCArIFRyZWVNYXAsIENvbWJpbmVkID0gcmVwbGFjZShDb21iaW5lZCwgMiwgbl9hdXRob3JzKSkgJT4lICAKICByZW5hbWUoIk51bWJlciBvZiIgPSAiTnVtYmVyIiwgIlBhcmFmaXQgKG4pIiA9ICJQYXJhZml0IiwgIlRyZWVNYXAgKG4pIiA9ICJUcmVlTWFwIiwgICJDb21iaW5lZCAobikiID0gIkNvbWJpbmVkIikgJT4lIAogIGthYmxlKCkgJT4lIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjI1MHB4IikKICAjcGFuZGVyKHNwbGl0LmNlbGwgPSA0MCwgc3BsaXQudGFibGUgPSBJbmYpICMgbm90IGFzIG5pY2UgYXMga2FibGUKYGBgCk5vdGUgdGhhdCBmb3IgdGhlIG51bWJlcnMgb2YgcGFwZXJzIGRvIG5vdCBhZGQgdXAgKFRyZWVNYXAgKyBQYXJhZml0ICRcbmVxJCBDb21iaW5lZCkgYmVjdWFzZSBgciBzdW0obl90YWJsZTJbMixdKSAtIGxlbmd0aCh1bmlxdWUoZGF0JGF1dGhvcnMpKWAgIHBhcGVycyB1c2VkIGJvdGggVHJlZU1hcCBhbmQgUGFyYWZpdCBtZXRob2RzICh0aGUgdGVybSAicGFwZXJzIiBoZXJlIGlzIG91ciB2YXJpYWJsZSBgYXVodG9yc2ApCgojIyMgTWlzc2luZyBkYXRhIHBhdHRlcm5zCgpIZXJlIHdlIGhhdmUgdGhlIG51bWJlciBvZiBtaXNzaW5nIGRhdGEgKGNlbGxzKSBmb3IgYWxsIHRoZSB2YXJhaWJsZXMgdXNlZCBpbiB0aGUgYW5hbHlzaXMgYmVsb3cuCgpgYGB7cn0KIyBzdW1tYXJpbmcgbWlzc2luZ25lc3MgaW4gb3VyIGRhdGFzZXQKIyBmdW5zKHN1bShpcy5uYSguKSkpIG5lZWRzIHRvIGJlIGluIGZ1bnMgYXMgaXMubmEgaGFzICIuIiA9IGVhY2ggY29sdW1uCmRhdCAlPiUgc3VtbWFyaXNlX2FsbCh+c3VtKGlzLm5hKC4pKSkgJT4lICMgbWFwKH5zdW0oaXMubmEoLikpICMgdGhpcyBpcyBhbiBhbHRlcmFudGl2ZSB3YXkgCiAgdCgpICU+JSBhc190aWJibGUocm93bmFtZXMgPSAiVmFyaWFibGUiKSAlPiUgCiAgcmVuYW1lKCJOdW1iZXIgb2YgbWlzc2luZyBkYXRhIChuKSIgPSAiVjEiKSAlPiUgCiAgI3BhbmRlcihzcGxpdC5jZWxsID0gNDAsIHNwbGl0LnRhYmxlID0gSW5mKQogIGthYmxlKCkgJT4lIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICI2MCUiLCBoZWlnaHQgPSAiMjUwcHgiKQoKIyBhbiBhbHRlcm5hdGl2ZSBtZXRob2QgdXNpbmcgdGhlIG1pIHBhY2thZ2UKI21pc3NpbmdfZGF0YV90YmwgPC0gbWlzc2luZ19kYXRhLmZyYW1lKGFzLmRhdGEuZnJhbWUoZGF0YSkpCiNzaG93KG1pc3NpbmdfZGF0YV90YmwpIApgYGAKCiMjIE1ldGEtYW5hbHlzaXMKCiMjIyBDYWxjdWxhdGluZyBlZmZlY3Qgc2l6ZXMKCkhlcmUsIHdlIGNyZWF0ZGUgb3VyIGVmZmVjdCBzaXplIChjb3JyZWxhdGlvbiBjb2VmZmljZW50ICpyKiBhbmQgaXRzIEZpc2hlcidzIHogdHJhbnNmb3JtYWl0b24gKlpyKikgZnJvbSBwIHZhbHVlcyBhbmQgYXNzb2NpYXRlZCBzYW1wbGUgc2l6ZXMuIFdlIHVzZWQgdGhlIHN1bSBvZiBgaG9zdF90aXBzX2xpbmtlZF9jb3JyZWN0ZWRgIGFuZCBgc3ltYmlvbnRfdGlwc19saW5rZWRgIGFzIG91ciBzYW1wbGUgc2l6ZSAoaS5lLiwgdGhlIG51bWJlciBvZiBib3RoIGhvc3QgYW5kIHN5bWJpb250IHNwZWNpZXMpIGZvciBlYWNoIGVmZmVjdCBzaXplIChhbiBpbmRpY2F0b3Igb2YgY29uZ3J1ZW5jZSkuIEFsc28sIHdlIGNyZWF0IGEgY29sdW1uIHdpdGggdW5pcXVlIElEIGZvciBlYWNoIG9ic2VydmF0aW9uIChpLmUuIGFuIG9ic2VydmF0aW9uIGxldmVsIHJhbmRvbSBlZmZlY3QpLCB0ZXJtZWQgYG9ic2VydmF0aW9uYCwgd2hpY2ggaXMgcmVxdWlyZWQgZm9yIHRoZSBgcm1hLm12YCBmdW5jdGlvbiBpbiBgbWV0YWZvcmAuCgpgYGB7cn0KZGF0ICU8PiUgCiAgIyBnZXR0aW5nIHNhbXBsZSBzaXplICYgb2JzZXJ2YXRpb24gbGV2ZWwgcmFuZG9tIGVmZmVjdAogIG11dGF0ZSguLCBzYW1wbGVfc2l6ZSA9IGhvc3RfdGlwc19saW5rZWRfY29ycmVjdGVkICsgc3ltYmlvbnRfdGlwc19saW5rZWQsIG9ic2VydmF0aW9uID0gZmFjdG9yKDE6bnJvdyguKSkpICAKIyBjYWxjdWF0aW5nIGVmZmVjdCBzaXplIAojIHNvbWVob3cgaXQgZGlkIG5vdCBydW4gYnkgcGlwaW5nIHdpdGggYWJvdmUgKG5vdCByZWNvZ25pc2luZyB0aGUgZmlyc3QgYXVyZ3VtZW50KSAgCmRhdCAlPD4lIHBfdG9fWnIocF92YWx1ZSwgc2FtcGxlX3NpemUpIAoKIyBUT0RPCiMgc29tZSBmYWN0b3IgcmVvcmRlcmluZyByZXF1aXJlZCEhIQpsZXZlbHMgPSBjKCJzbWFsbCIsICJtZWRpdW0iLCAibGFyZ2UiKQpgYGAKCgojIyMgTWV0YS1hbmFseXRpYyBtb2RlbDogdGVzdGluZyBGYWhyZW5ob2x6J3MgcnVsZQoKRmlyc3QsIHdlIGNoZWNrZWQgd2hhdCByYW5kb20gZWZmZWN0cyBzaG91bGQgYmUgcHV0IGludG8gdGhlIG1haW4gbW9kZWwgdG8gZG8gdGhpcyB3ZSBmaXR0ZWQgdHdvIHJhbmRvbSBlZmZlY3RzLCBgYXV0aG9yc2AgYW5kIGBvYnNlcnZhdGlvbmA7IHRoZSBmb3JtZXIgdGVybSB3YXMgYWRkZWQgdG8gYWNjb3VudCBmb3Igbm9uLWluZGVwZW5kZW5jZSBvZiBlZmZlY3Qgc2l6ZXMgb3JnaW5hdGluZyBmcm9tIHRoZSBzYW1lIHBhcGVycyAoaS5lLiwgYGF1dGhvcnNgKS4gCgpgYGB7ciwgY2FjaGU9VFJVRX0KIyAyIHJhbmRvbSBlZmZlY3RzICYgbW9kZWwgQUlDIAojIG5vdGUgdGhhdCBwcm9iYWJseSBvbmx5IGJhc2Ugc3R1ZmYgd29ya3Mgb3V0c2lkZSBvZiBtYWluIGNodW5jayBzbyBuZWVkIHRvIGNyZWF0ZSBBSUMgaGVyZQptYV90ZXN0MSA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IGxpc3QofiAxIHwgYXV0aG9ycywgfjF8b2JzZXJ2YXRpb24pLCAKICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCmFpYzEgPC0gQUlDKG1hX3Rlc3QxKQoKIyAxIHJhbmRvbSBlZmZlY3QgJiBtb2RlbCBBSUMgCm1hX3Rlc3QyIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQphaWMyIDwtIEFJQyhtYV90ZXN0MikKYGBgCgpUaGUgbW9kZWwgKGBtYV90ZXN0MWApLCB3aGljaCBpbmNsdWRlZCBib3RoIHJhbmRvbSBmYWN0b3JzLCBoYWQgYSBsYXJnZXIgQUlDIHZhbHVlIChgciByb3VuZChhaWMxLDIpYCkgdGhhbiB0aGUgbW9kZWwgd2l0aCBvbmx5IG9uZSByYW5kb20gZWZmZWN0IChgciByb3VuZChhaWMyLCAyKWApIC4gVGhpcyBpcyBiZWN1YXNlIGBvYnNlcnZhdGlvbmAgaGFyZGx5IGFjY291bnRlZCBhbnkgdmFyaWFuY2UgKDwgMC4wMDAxKSBjb21wYXJlZCB0byBgYXV0aG9yc2AgKGByIHJvdW5kKG1hX3Rlc3QxJHNpZ21hMlsxXSwgNClgKS4gVGhlcmVmb3JlLCB3ZSBvbmx5IGhhZCBgYXV0aG9yc2AgYXMgb3VyIHJhbmRvbSBmYWN0b3IgaW4gc3Vic3F1ZW50YiBhbmFseXNlcy4KCldlIHJhbiBpbnRlcmNlcHQgbW9kZWxzIChtZXRhLWFuYWx5c2VzKSB3aXRoIDMgZGlmZmVyZW50IGRhdGFzZXRzIChgUGFyYWZpdGAsIGBUcmVlTWFwYCBhbmQgYm90aCBjb21iaW5lZDsgc2VlIHRoZSBleHBsYW50aW9uIG9mIGBtZXRob2RgIGFib3ZlKS4gQWxzbywgd2Ugbm90ZSB0aGF0IHdlIHVzZWQgYWRqdXN0bWVudHMgZm9yIHRlc3Qgc3RhdGlzdGljcyBhbmQgY29uZmlkZW5jZSBpbnRlcnZhbHMgKGB0ZXN0ID0gInQiYCksIHdoaWNoIGlzIHNpbWlsYXIgdG8gKGJ1dCBub3QgdGhlIHNhbWUgYXMpIHRob3NlIHByb3Bvc2VkIGJ5IEthbnBwIGFuZCBIYXJ0dW5nICgyMDAzKTsgcHJvYmFibHkgdGhpcyBhcHByb2NoIGlzIGEgbW9yZSBjb25zZXJ2YXRpdmUgYXBwcm9hY2guCgojIyMgUnVubmluZyBNdWx0aWxldmVsIE1ldGEtYW5hbHl0aWMgbW9kZWxzIHdpdGggMyBkYXRhc2V0cwpgYGB7ciwgY2FjaGU9VFJVRX0KIyB0aGluayBhYm91dCBtYWtpbmcgdGhpcyBpbnRvIGEgdGliYmxlCiMgbWV0YS1hbmFseXNpcyB3aXRoIFBhcmFmaXQKbWFfcGFyYWZpdCA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICBzdWJzZXQgPSB3aGljaChtZXRob2QgPT0gIlRyZWVNYXAiKSwKICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQoKIyBtZXRhLWFuYWx5c2lzIHdpdGggVHJlZU1hcAptYV90cmVlbWFwIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgIHN1YnNldCA9IHdoaWNoKG1ldGhvZCA9PSAiUGFyYWZpdCIpLAogICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtYW5hbHlzaXMgd2l0aCBhbGwgdGhlIGRhdGEgY29tYmluZWQKbWFfYWxsIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCmBgYAoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDE6KioKT3ZlcmFsbCBlZmZlY3RzIChtZXRhLWFuYWx5dGljIG1lYW5zKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgaGV0ZXJvZ2VuZWl0eSwgKkkqXjJeIChJMikgZnJvbSBgbWV0YWZvcmAgbW9kZWwgdXNpbmcgdGhlIDMgZGF0YXNldHMgKGBQYXJhZml0YCwgYFRyZWVNYXBgIGFuZCBib3RoIGNvbWJpbmVkLCBvciBgQWxsYCkuIE5vdGUgdGhhdCBpbiB0aGVzZSBtb2RlbHMsICpJKl4yXn5bdG90YWxdfiA9ICpJKl4yXn5bYXV0aG9yc11+IChzZWUgTmFrYWdhd2EgJiBTYW50b3MgMjAxMjsgUkVGIC0gcHJvYmFibHkgU2VuaW9yIGFzIHdlbGw/KSwgYXMgd2Ugb25seSBoYXZlIG9uZSByYW5kb20gZmFjdG9yLiAKYGBge3J9CiMgZ2V0dGluZyBJMiBmb3IgdGhlIG1vZGVscwojIGNvdWxkIHVzZSBtYXAoKQppMl90cmVlbWFwIDwtIEkyKG1hX3RyZWVtYXApCmkyX3BhcmFmaXQgPC0gSTIobWFfcGFyYWZpdCkKaTJfYWxsIDwtIEkyKG1hX2FsbCkKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBEYXRhc2V0ID0gYygiUGFyYWZpdCIsICJUcmVlTWFwIiwgIkFsbCIpLAogIGBPdmVyYWxsIG1lYW4gKFpyKWAgPSBjKG1hX3BhcmFmaXQkYiwgbWFfdHJlZW1hcCRiLCBtYV9hbGwkYiksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhtYV9wYXJhZml0JGNpLmxiLCBtYV90cmVlbWFwJGNpLmxiLCBtYV9hbGwkY2kubGIpLAogIGBVcHBlciBDICBbMC45NzVdYCA9IGMobWFfcGFyYWZpdCRjaS51YiwgbWFfdHJlZW1hcCRjaS51YiwgbWFfYWxsJGNpLnViKSwKICBgVlthdXRob3JzXWAgPSBjKG1hX3BhcmFmaXQkc2lnbWEyLCBtYV90cmVlbWFwJHNpZ21hMiwgbWFfYWxsJHNpZ21hMiksCiAgYEkyW3RvdGFsXWAgPSBjKGkyX3BhcmFmaXRbMV0sIGkyX3RyZWVtYXBbMV0sIGkyX2FsbFsxXSkpJT4lIGthYmxlKCJodG1sIiwgIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCgpUaGVzZSBtb2RlbHMgZ2F2ZSBhbGwgY29uc2lzdGFudCByZXN1bHRzIGluY2x1ZGluZyBoZXRlcm9nZW5laXR5LiBHaXZlbiB0aGVzZSByZXN1bHRzLCB3ZSBwcm9jZWVkZWQgd2l0aCBvbmx5IGFuYWx5c2luZyB0aGUgd2hvbGUgZGF0YXNldCAoYEFsbGApIGZyb20gdGhpcyBvbi4gICAgCgpgYGB7ciwgIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTIuNX0KIyBjcmVhdGluZyBhIHRhYmxlIG9mIHJlc3VsdHMKcHJlZF9tYSA8LSBnZXRfcHJlZChtYV9hbGwpIAplZmZlY3RfbWEgPC0gZ2V0X2VzdChtYV9hbGwpICU+JSBsZWZ0X2pvaW4ocHJlZF9tYSkgCgojIGNyZWF0aW5nIGEgZm9yZXN0IHBsb3QKZmlnX21hIDwtIGdncGxvdChkYXRhID0gZWZmZWN0X21hLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gIk92ZXJhbGwgbWVhbiIpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC0xLCAxKSwgYnJlYWtzID0gc2VxKC0xLCAxLCBieSA9IDAuMikgKSArCiAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0LCBhZXMoeD0gdGFuaChaciksIHkgPSAiT3ZlcmFsbCBtZWFuIiwgc2l6ZSA9ICgxL1ZacikgKyAzKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC4yKSArIAogICMgcHJlY2l0aW9uIGludGVydmFsIChQSSkKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJQUiksIHhtYXggPSB0YW5oKHVwcGVyUFIpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjYpICsKICAjIENJCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyQ0wpLCB4bWF4ID0gdGFuaCh1cHBlckNMKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAxLjIpICsKCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogICMgY3JlYXRpbmcgZG90cyBhbmQgZGlmZmVyZW50IHNpemUgKGJlZS1zd2FybSBhbmQgYnViYmxlcykKICBnZW9tX3BvaW50KHNpemU9Mywgc2hhcGU9MjEsIGZpbGwgPSAiYmxhY2siKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gLTEsIHkgPSAiT3ZlcmFsbCBtZWFuIiwgbGFiZWw9cGFzdGUoIml0YWxpYyhrKT09IiwgbGVuZ3RoKGRhdCRacikpLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMpIikpICkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgCgojZ2dzYXZlKHBsb3QgPSBmaWdfbWEsIGZpbGVuYW1lID0gImZpZ18yYS5wZGYiLCBoZWlnaHQgPSAyLCB3aWR0aCA9IDgpCiMgZ2dwbG90eSAwIGRvZXMgbm90IHdvcmsgKEVycm9yIGluIHVuaXF1ZS5kZWZhdWx0KHgpIDogdW5pbXBsZW1lbnRlZCB0eXBlICdleHByZXNzaW9uJyBpbiAnSGFzaFRhYmxlU2V0dXAnKQpmaWdfbWEKYGBgCgoqKkZpZ3VyZSAyYToqKiBUaGUgZWZmZWN0IFhYWFhYWAoKIyMgTWV0YS1yZWdyZXNzaW9uCgpXZSByYW4gYSB1bml2YXJhaXRlIG1ldGEtcmVncmVzc2lvbiBtb2RlbCBmb3IgZWFjaCBvZiBmb2xsb3dpbmcgbW9kZXJhdG9yczogMSkgYHN5bWJpb3Npc2AsIDIpIGBob3N0X3RheF9icm9hZGAsIDMpIGBzeW1iaW9udF90YXhfYnJvYWRgLCA0KSBgaG9zdF9yYW5nZV9saW5rX3JhdGlvYCwgNSkgYGhvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGhgLCA2KSBgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWRgLCBhbmQgNykgYGVuZG9fb3JfZWN0b2AuIFRoZSByZXN1bHRzIGZyb20gdGhlc2UgbW9kZWxzIGFyZSBwcmVzZW50ZWQgaW4gdGhlIG1haW4gdGV4dC4gCgpJbiBhZGR0aW9uIHRvIHRoZXNlLCB3ZSByYW4gdGhyZWUgbW9yZSB1bml2YXJpYXRlIG1vZGVsczogMSkgYGhvc3RfdGF4X3N5bWJpb3Npc2AgKGVxdWl2YWxlbnQgdG8gdGhlIGludGVyYWN0b2luIHRlcm0gYmV0d2VlbiBgc3ltYmlvc2lzYCBhbmQgYGhvc3RfdGF4X3N5bWJpb3Npc2A7IGBzeW1iaW9zaXMqaG9zdF90YXhfc3ltYmlvc2lzYCksIDIpIGBzeW1iaW9udF90YXhfc3ltYmlvc2lzYCAoYHN5bWJpb3NpcypzeW1iaW9udF90YXhfYnJvYWRgKSwgIDMpIGBob3N0X3N5bWJpb250X3RheGAgKGBob3N0X3RheF9zeW1iaW9zaXMqc3ltYmlvbnRfdGF4X2Jyb2FkYCkgYW5kIDQpIGBzeW1iaW9zaXNfdHJhbnNtaXNzaW9uYCAoYHN5bWJpb3Npcyptb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZGApLiBUaGVyZSBtb2RlcmF0b3JzIGFyZSBjcmVhdGVkIGJlbG93OgoKYGBge3J9CmRhdCAlPD4lIAogICAgIyBob3N0X3RheF9icm9hZCpzeW1iaW9zaXMgKGhvc3RfdGF4X3N5bWJpb3NpcykgCiAgbXV0YXRlKGhvc3RfdGF4X3N5bWJpb3NpcyA9IHN0cl9jKGhvc3RfdGF4X2Jyb2FkLCBzeW1iaW9zaXMpLCAKICAgICAgICAgaG9zdF90YXhfc3ltYmlvc2lzID0gaWZlbHNlKGhvc3RfdGF4X3N5bWJpb3NpcyA9PSAiSW52ZXJ0TkEiLCBOQSwgaG9zdF90YXhfc3ltYmlvc2lzKSwKICAgICAgICAgaG9zdF90YXhfc3ltYmlvc2lzID0gZmFjdG9yKGhvc3RfdGF4X3N5bWJpb3NpcyksCiAgICAgICAgICMgc3ltYmlvbnRfdGF4X2Jyb2FkKnN5bWJpb3NpcyAoc3ltYmlvbnRfdGF4X3N5bWJpb3NpcykgICAgIAogICAgICAgICBzeW1iaW9udF90YXhfc3ltYmlvc2lzID0gZmFjdG9yKHN0cl9jKHN5bWJpb250X3RheF9icm9hZCwgc3ltYmlvc2lzKSksCiAgICAgICAgICMgaG9zdF90YXhfYnJvYWQqc3ltYmlvbnRfdGF4X2Jyb2FkIChob3N0X3N5bWJpb250X3RheCkgICAgIAogICAgICAgICBob3N0X3N5bWJpb250X3RheCAgPSBmYWN0b3Ioc3RyX2MoaG9zdF90YXhfYnJvYWQsIHN5bWJpb250X3RheF9icm9hZCkpLAogICAgICAgICAjIHN5bWJpb3Npcyptb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCAoc3ltYmlvc2lzX3RyYW5zbWlzc2lvbikKICAgICAgICAgc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiAgPSBmYWN0b3Ioc3RyX2Moc3ltYmlvc2lzLCBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCkpLAogICAgICAgICAjIHdoZXRoZXIgcCB2YWx1ZXMgd2VyZSB0aGUgc21hbGxlc3QgdmFsdWUgZ2l2ZW4gdGhlIG51bWJlciBvZiByYW5kYW1pemF0aW9uIC0gbGltaXRfcmVzZWFyY2hlZCAoWWVzID0gMSwgTm8gPSAwKQogICAgICAgICBsaW1pdF9yZWFyY2hlZCA9IGlmX2Vsc2UoYWJzKCgxL3BfdmFsdWUpIC0gbm9fcmFuZG9taXphdGlvbnMpIDw9IDEsIDEsIDApKQoKYGBgCgojIyMgVW5pdmFyYWl0ZSAoVW5pLXByZWRpY3RvcikgYW5hbHlzZXMKCiMjIyBUaGUgdHlwZSBvZiBzeW1iaW9zaXM6IHBhcmFzaXRpc20gdnMuIG11dHVhbGlzbQoKYGBge3J9CiMgbWV0YS1yZWdyZXNzaW9uOiBtdXRpcGxlIGludGVyY2VwdHMKbXJfc3ltYmlvc2lzMSA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gc3ltYmlvc2lzIC0gMSwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QKbXJfc3ltYmlvc2lzMiA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gc3ltYmlvc2lzLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCmBgYAoqKlN1cHBsZW1lbnRhcnkgVGFibGUgMjoqKgpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleGFtcGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYHN5bWJpb3Npc2AuIAoKYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9zeW1iaW9zaXMxIDwtIFIyKG1yX3N5bWJpb3NpczEpCgojIGdldHRpbmcgZXN0aW1hdGVzCnJlc19zeW1iaW9zaXMxIDwtIGdldF9lc3QobXJfc3ltYmlvc2lzMSwgbW9kID0gInN5bWJpb3NpcyIpCnJlc19zeW1iaW9zaXMyIDwtIGdldF9lc3QobXJfc3ltYmlvc2lzMiwgbW9kID0gInN5bWJpb3NpcyIpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX3N5bWJpb3NpczEkbmFtZSksIGNvbnRfZ2VuKHJlc19zeW1iaW9zaXMxJG5hbWUpKSwKICBFc3RpbWF0ZSA9IGMocmVzX3N5bWJpb3NpczEkZXN0aW1hdGUsIHJlc19zeW1iaW9zaXMyJGVzdGltYXRlWzJdKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19zeW1iaW9zaXMxJGxvd2VyQ0wsIHJlc19zeW1iaW9zaXMyJGxvd2VyQ0xbMl0pLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19zeW1iaW9zaXMxJHVwcGVyQ0wsIHJlc19zeW1iaW9zaXMyJHVwcGVyQ0xbMl0pLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfc3ltYmlvc2lzMSRzaWdtYTIsICByZXAoTkEsIDIpKSwKICBgUjJgID0gYyhyMl9zeW1iaW9zaXMxWzFdLCByZXAoTkEsIDIpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKYGBgCgoKCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0yLjV9CiMgYWRkaW5nIHNhbXBsZSBzaXplIChrKSBmb3IgZWFjaCBjYXRlZ29yeQprX3N5bWJpb3NpcyA8LSBkYXQgJT4lIGdyb3VwX2J5KHN5bWJpb3NpcykgJT4lIGNvdW50KCkKIyBnZXR0aW5nIGVzdGltYXRlcyBhbmQgcHJlZGljaXRvbnMKcHJlZF9zeW1iaW9zaXMgPC0gZ2V0X3ByZWQobXJfc3ltYmlvc2lzMSwgbW9kID0gInN5bWJpb3NpcyIpIApyZXNfc3ltYmlvc2lzMSA8LSBsZWZ0X2pvaW4ocmVzX3N5bWJpb3NpczEsIGtfc3ltYmlvc2lzLCBieSA9ICBjKCJuYW1lIiA9ICJzeW1iaW9zaXMiKSkgICU+JSBsZWZ0X2pvaW4ocHJlZF9zeW1iaW9zaXMpCiNyZXNfc3ltYmlvc2lzMSAKIyBkcmF3aW5nIGEgZnVubmVsIHBsb3QgLSBmaWcgMmIKZmlnX3N5bWJpb3NpcyA8LSBnZ3Bsb3QoZGF0YSA9IHJlc19zeW1iaW9zaXMxLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoc3ltYmlvc2lzKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gc3ltYmlvc2lzLCBzaXplID0gKCgxL1ZacikgKyAzKSwgY29sb3VyID0gc3ltYmlvc2lzKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC4yKSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiTXV0dWFsaXN0IiA9ICIjRTY5RjAwIiwgIlBhcmFzaXRlIiA9ICIjNTZCNEU5IikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNdXR1YWxpc3QiID0gIiNFNjlGMDAiLCAiUGFyYXNpdGUiID0gIiM1NkI0RTkiKSkgKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IC0xLCB5ID0gcmVzX3N5bWJpb3NpczEkbmFtZSwgbGFiZWw9IHBhc3RlKCJpdGFsaWMoayk9PSIsIHJlc19zeW1iaW9zaXMxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMpIikpICkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIpICsKICAjdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKSArCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ImJsYWNrIiwgaGp1c3QgPSAwLjUsIGFuZ2xlID0gOTApKSAKCmZpZ19zeW1iaW9zaXMKYGBgCgoqKkZpZ3VyZSAyYjoqKiBUaGUgZWZmZWN0IFhYWFhYWAoKIyMjIFRoZSBlZmZlY3Qgb2YgaG9zdCB0YXhhCgpgYGB7cn0KIyByZW9yZGVyaW5nCmRhdCRob3N0X3RheF9icm9hZCA8LSBmYWN0b3IoZGF0JGhvc3RfdGF4X2Jyb2FkLCBsZXZlbHMgPSBjKCJNaWNyb2JlIiwgIlBsYW50IiwgIkludmVydCIsICJWZXJ0IikpCgojIG1ldGEtcmVncmVzc2lvbjogbXV0aXBsZSBpbnRlcmNlcHRzCm1yX2hvc3RfdGF4X2Jyb2FkMSA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gaG9zdF90YXhfYnJvYWQgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMQptcl9ob3N0X3RheF9icm9hZDIgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IGhvc3RfdGF4X2Jyb2FkLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMgptcl9ob3N0X3RheF9icm9hZDMgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoaG9zdF90YXhfYnJvYWQsIHJlZiA9ICJQbGFudCIpLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMwptcl9ob3N0X3RheF9icm9hZDQgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoaG9zdF90YXhfYnJvYWQsIHJlZiA9ICJJbnZlcnQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQpgYGAKCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgaG9zdF90YXhfYnJvYWRgLiAKYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9ob3N0X3RheF9icm9hZDEgPC0gUjIobXJfaG9zdF90YXhfYnJvYWQxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfaG9zdF90YXhfYnJvYWQxIDwtIGdldF9lc3QobXJfaG9zdF90YXhfYnJvYWQxLCBtb2QgPSAiaG9zdF90YXhfYnJvYWQiKQpyZXNfaG9zdF90YXhfYnJvYWQyIDwtIGdldF9lc3QobXJfaG9zdF90YXhfYnJvYWQyLCBtb2QgPSAiaG9zdF90YXhfYnJvYWQiKQojIHRoZSBuYW1lIGJpdCBkb2VzIG5vdCB3b3JrIGlmIHJlbGV2ZWwuLi4uCnJlc19ob3N0X3RheF9icm9hZDMgPC0gZ2V0X2VzdChtcl9ob3N0X3RheF9icm9hZDMsIG1vZCA9ICJob3N0X3RheF9icm9hZCIpCnJlc19ob3N0X3RheF9icm9hZDQgPC0gZ2V0X2VzdChtcl9ob3N0X3RheF9icm9hZDQsIG1vZCA9ICJob3N0X3RheF9icm9hZCIpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX2hvc3RfdGF4X2Jyb2FkMSRuYW1lKSwgY29udF9nZW4ocmVzX2hvc3RfdGF4X2Jyb2FkMSRuYW1lKSksCiAgRXN0aW1hdGUgPSBjKHJlc19ob3N0X3RheF9icm9hZDEkZXN0aW1hdGUsIHJlc19ob3N0X3RheF9icm9hZDIkZXN0aW1hdGVbLTFdLCAgcmVzX2hvc3RfdGF4X2Jyb2FkMyRlc3RpbWF0ZVstKDE6MildLCByZXNfaG9zdF90YXhfYnJvYWQ0JGVzdGltYXRlWy0oMTozKV0pLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMocmVzX2hvc3RfdGF4X2Jyb2FkMSRsb3dlckNMLCByZXNfaG9zdF90YXhfYnJvYWQyJGxvd2VyQ0xbLTFdLCByZXNfaG9zdF90YXhfYnJvYWQzJGxvd2VyQ0xbLSgxOjIpXSwgcmVzX2hvc3RfdGF4X2Jyb2FkNCRsb3dlckNMWy0oMTozKV0pLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19ob3N0X3RheF9icm9hZDEkdXBwZXJDTCwgcmVzX2hvc3RfdGF4X2Jyb2FkMiR1cHBlckNMWy0xXSwgcmVzX2hvc3RfdGF4X2Jyb2FkMyR1cHBlckNMWy0oMToyKV0sIHJlc19ob3N0X3RheF9icm9hZDQkdXBwZXJDTFstKDE6MyldKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX2hvc3RfdGF4X2Jyb2FkMSRzaWdtYTIsICByZXAoTkEsIDkpKSwKICBgUjJgID0gYyhyMl9ob3N0X3RheF9icm9hZDFbMV0sIHJlcChOQSwgOSkpKSAlPiUga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIzMDBweCIpCmBgYAoKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSA0fQojIGFkZGluZyBzYW1wbGUgc2l6ZSAoaykgZm9yIGVhY2ggY2F0ZWdvcnkKa19ob3N0X3RheF9icm9hZCA8LSBkYXQgJT4lIGdyb3VwX2J5KGhvc3RfdGF4X2Jyb2FkKSAlPiUgY291bnQoKQojIGdldHRpbmcgZXN0aW1hdGVzIGFuZCBwcmVkaWNpdG9ucwpwcmVkX2hvc3RfdGF4X2Jyb2FkIDwtIGdldF9wcmVkKG1yX2hvc3RfdGF4X2Jyb2FkMSwgbW9kID0gImhvc3RfdGF4X2Jyb2FkIikgCnJlc19ob3N0X3RheF9icm9hZDEgPC0gbGVmdF9qb2luKHJlc19ob3N0X3RheF9icm9hZDEsIGtfaG9zdF90YXhfYnJvYWQsIGJ5ID0gIGMoIm5hbWUiID0gImhvc3RfdGF4X2Jyb2FkIikpICAlPiUgbGVmdF9qb2luKHByZWRfaG9zdF90YXhfYnJvYWQpCiNyZXNfc3ltYmlvc2lzMSAKIyBkcmF3aW5nIGEgZnVubmVsIHBsb3QgLSBmaWcgMmIKZmlnX2hvc3RfdGF4X2Jyb2FkIDwtIGdncGxvdChkYXRhID0gcmVzX2hvc3RfdGF4X2Jyb2FkMSwgYWVzKHggPSB0YW5oKGVzdGltYXRlKSwgeSA9IG5hbWUpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC0xLCAxKSwgYnJlYWtzID0gc2VxKC0xLCAxLCBieSA9IDAuMikgKSArCiAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0ICU+JSBmaWx0ZXIoIWlzLm5hKGhvc3RfdGF4X2Jyb2FkKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gaG9zdF90YXhfYnJvYWQsIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBob3N0X3RheF9icm9hZCksIGdyb3VwT25YID0gRkFMU0UsIGFscGhhPTAuNCkgKyAKICAjIDk1ICVwcmVjaXRpb24gaW50ZXJ2YWwgKFBJKQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlclBSKSwgeG1heCA9IHRhbmgodXBwZXJQUikpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMC41LCBhbHBoYSA9IDAuNikgKwogICMgOTUgJUNJCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyQ0wpLCB4bWF4ID0gdGFuaCh1cHBlckNMKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAxLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJibGFjayIsIGFscGhhID0gMC4zKSArCiAgIyBjcmVhdGluZyBkb3RzIGFuZCBkaWZmZXJlbnQgc2l6ZSAoYmVlLXN3YXJtIGFuZCBidWJibGVzKQogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBuYW1lKSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEpICsgIwogICMgc2V0dGluZyBjb2xvdXJzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk1pY3JvYmUiID0gIiMwMDlFNzMiLCAgIlBsYW50IiA9ICIjRjBFNDIyIiwgICJJbnZlcnQiPSAiIzAwNzJCMiIsICAiVmVydCIgPSAiI0Q1NUUwMCIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTWljcm9iZSIgPSAiIzAwOUU3MyIsICAiUGxhbnQiID0gIiNGMEU0MjIiLCAgIkludmVydCI9ICIjMDA3MkIyIiwgICJWZXJ0IiA9ICIjRDU1RTAwIikpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIk1pY3JvYmUiID0gIk1pY3JvYmUiLCAgIlBsYW50IiA9ICJQbGFudCIsICAiSW52ZXJ0Ij0gIkludmVydGVicmF0ZSIsICAiVmVydCIgPSAiVmVydGVicmF0ZSIpKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gLTEsIHkgPSByZXNfaG9zdF90YXhfYnJvYWQxJG5hbWUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfaG9zdF90YXhfYnJvYWQxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMpIikpICkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIpICsKICAjdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKSArCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ImJsYWNrIiwgaGp1c3QgPSAwLjUsIGFuZ2xlID0gOTApKSAKCmZpZ19ob3N0X3RheF9icm9hZApgYGAKCioqRmlndXJlIDJjOioqIFRoZSBlZmZlY3QgWFhYWFhYCgojIyMgVGhlIGVmZmVjdCBvZiBzeW1iaW9udCB0YXhhCgpgYGB7cn0KIyByZW9yZGVyaW5nCmRhdCRzeW1iaW9udF90YXhfYnJvYWQgPC0gZmFjdG9yKGRhdCRzeW1iaW9udF90YXhfYnJvYWQsIGxldmVscyA9IGMoIk1pY3JvYmUiLCAiUGxhbnQiLCAiSW52ZXJ0IiwgIlZlcnQiKSkKCiNzaXplcyA8LSBmYWN0b3Ioc2l6ZXMsIGxldmVscyA9IGMoInNtYWxsIiwgIm1lZGl1bSIsICJsYXJnZSIpKQojc2l6ZXMKIz4gWzFdIHNtYWxsICBsYXJnZSAgbGFyZ2UgIHNtYWxsICBtZWRpdW0KIz4gTGV2ZWxzOiBzbWFsbCBtZWRpdW0gbGFyZ2UKIyBtZXRhLXJlZ3Jlc3Npb246IG11dGlwbGUgaW50ZXJjZXB0cwptcl9zeW1iaW9udF90YXhfYnJvYWQxIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBzeW1iaW9udF90YXhfYnJvYWQgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMQptcl9zeW1iaW9udF90YXhfYnJvYWQyIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBzeW1iaW9udF90YXhfYnJvYWQsIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdCAyCm1yX3N5bWJpb250X3RheF9icm9hZDMgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoc3ltYmlvbnRfdGF4X2Jyb2FkLCByZWYgPSAiUGxhbnQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQoKIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0IDMKbXJfc3ltYmlvbnRfdGF4X2Jyb2FkNCA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gcmVsZXZlbChzeW1iaW9udF90YXhfYnJvYWQsIHJlZiA9ICJJbnZlcnQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQpgYGAKCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgc3ltYmlvbnRfdGF4X2Jyb2FkYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfc3ltYmlvbnRfdGF4X2Jyb2FkMSA8LSBSMihtcl9zeW1iaW9udF90YXhfYnJvYWQxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSA8LSBnZXRfZXN0KG1yX3N5bWJpb250X3RheF9icm9hZDEsIG1vZCA9ICJzeW1iaW9udF90YXhfYnJvYWQiKQpyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMiA8LSBnZXRfZXN0KG1yX3N5bWJpb250X3RheF9icm9hZDIsIG1vZCA9ICJzeW1iaW9udF90YXhfYnJvYWQiKQpyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMyA8LSBnZXRfZXN0KG1yX3N5bWJpb250X3RheF9icm9hZDMsIG1vZCA9ICJzeW1iaW9udF90YXhfYnJvYWQiKQpyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkNCA8LSBnZXRfZXN0KG1yX3N5bWJpb250X3RheF9icm9hZDQsIG1vZCA9ICJzeW1iaW9udF90YXhfYnJvYWQiKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoYXMuY2hhcmFjdGVyKHJlc19zeW1iaW9udF90YXhfYnJvYWQxJG5hbWUpLCBjb250X2dlbihyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSRuYW1lKSksCiAgRXN0aW1hdGUgPSBjKHJlc19zeW1iaW9udF90YXhfYnJvYWQxJGVzdGltYXRlLCByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMiRlc3RpbWF0ZVstMV0sICByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMyRlc3RpbWF0ZVstKDE6MildLCByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkNCRlc3RpbWF0ZVstKDE6MyldKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19zeW1iaW9udF90YXhfYnJvYWQxJGxvd2VyQ0wsIHJlc19zeW1iaW9udF90YXhfYnJvYWQyJGxvd2VyQ0xbLTFdLCByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMyRsb3dlckNMWy0oMToyKV0sIHJlc19zeW1iaW9udF90YXhfYnJvYWQ0JGxvd2VyQ0xbLSgxOjMpXSksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX3N5bWJpb250X3RheF9icm9hZDEkdXBwZXJDTCwgcmVzX3N5bWJpb250X3RheF9icm9hZDIkdXBwZXJDTFstMV0sIHJlc19zeW1iaW9udF90YXhfYnJvYWQzJHVwcGVyQ0xbLSgxOjIpXSwgcmVzX3N5bWJpb250X3RheF9icm9hZDQkdXBwZXJDTFstKDE6MyldKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX3N5bWJpb250X3RheF9icm9hZDEkc2lnbWEyLCAgcmVwKE5BLCA5KSksCiAgYFIyYCA9IGMocjJfc3ltYmlvbnRfdGF4X2Jyb2FkMVsxXSwgcmVwKE5BLCA5KSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjMwMHB4IikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDR9CiMgYWRkaW5nIHNhbXBsZSBzaXplIChrKSBmb3IgZWFjaCBjYXRlZ29yeQprX3N5bWJpb250X3RheF9icm9hZCA8LSBkYXQgJT4lIGdyb3VwX2J5KHN5bWJpb250X3RheF9icm9hZCkgJT4lIGNvdW50KCkKIyBnZXR0aW5nIGVzdGltYXRlcyBhbmQgcHJlZGljaXRvbnMKcHJlZF9zeW1iaW9udF90YXhfYnJvYWQgPC0gZ2V0X3ByZWQobXJfc3ltYmlvbnRfdGF4X2Jyb2FkMSwgbW9kID0gInN5bWJpb250X3RheF9icm9hZCIpIApyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSA8LSBsZWZ0X2pvaW4ocmVzX3N5bWJpb250X3RheF9icm9hZDEsIGtfc3ltYmlvbnRfdGF4X2Jyb2FkLCBieSA9ICBjKCJuYW1lIiA9ICJzeW1iaW9udF90YXhfYnJvYWQiKSkgICU+JSBsZWZ0X2pvaW4ocHJlZF9zeW1iaW9udF90YXhfYnJvYWQpCiNyZXNfc3ltYmlvc2lzMSAKIyBkcmF3aW5nIGEgZnVubmVsIHBsb3QgLSBmaWcgMmIKZmlnX3N5bWJpb250X3RheF9icm9hZCA8LSBnZ3Bsb3QoZGF0YSA9IHJlc19zeW1iaW9udF90YXhfYnJvYWQxLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoc3ltYmlvbnRfdGF4X2Jyb2FkKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gc3ltYmlvbnRfdGF4X2Jyb2FkLCBzaXplID0gKCgxL1ZacikgKyAzKSwgY29sb3VyID0gc3ltYmlvbnRfdGF4X2Jyb2FkKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC40KSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiTWljcm9iZSIgPSAiIzAwOUU3MyIsICAiUGxhbnQiID0gIiNGMEU0MjIiLCAgIkludmVydCI9ICIjMDA3MkIyIiwgICJWZXJ0IiA9ICIjRDU1RTAwIiApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTWljcm9iZSIgPSAiIzAwOUU3MyIsICAiUGxhbnQiID0gIiNGMEU0MjIiLCAgIkludmVydCI9ICIjMDA3MkIyIiwgICJWZXJ0IiA9ICIjRDU1RTAwIikpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIk1pY3JvYmUiID0gIk1pY3JvYmUiLCAgIlBsYW50IiA9ICJQbGFudCIsICAiSW52ZXJ0Ij0gIkludmVydGVicmF0ZSIsICAiVmVydCIgPSAiVmVydGVicmF0ZSIpKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gLTEsIHkgPSByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSRuYW1lLCBsYWJlbD0gcGFzdGUoIml0YWxpYyhrKT09IiwgcmVzX3N5bWJpb250X3RheF9icm9hZDEkbiksIHBhcnNlPVRSVUUsIGhqdXN0ID0gImxlZnQiLCBzaXplPTMuNSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKHIpLCAiIChjb3JyZWxhdG9uKSIpKSwgeSA9ICIiLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcykiKSkgKSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG91ciA9ICJub25lIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZmlnX3N5bWJpb250X3RheF9icm9hZApgYGAKCioqRmlndXJlIDJkOioqIFRoZSBlZmZlY3QgWFhYWFhYCgojIyMgVGVzdGluZyBzcGVjaWFsaXphdGlvbiAxOiBob3N0IHJhbmdlCgpgYGB7cn0KIyBtZXRhLXJlZ3Jlc3Npb24KbXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvIDwtIHJtYS5tdih5aSA9IFpyLCBWID0gVlpyLCBtb2RzID0gfiBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKSwgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgZGF0YSA9IGRhdCkKCmBgYAoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDM6KioKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhhbXBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBzeW1iaW9udF90YXhfYnJvYWRgLiAKYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8gPC0gUjIobXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvKQoKIyBnZXR0aW5nIGVzdGltYXRlczogbmFtZSBkb2VzIG5vdCB3b3JrIGZvciBzbG9wZXMKcmVzX2hvc3RfcmFuZ2VfbGlua19yYXRpbyA8LSBnZXRfZXN0KG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbywgbW9kID0gImxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pIikKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKCJJbnRlcmNlcHQiLCAibG9nKGhvc3RfcmFuZ2VfbGlua19yYXRpbykiKSwKICBFc3RpbWF0ZSA9IGMocmVzX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRlc3RpbWF0ZSksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhyZXNfaG9zdF9yYW5nZV9saW5rX3JhdGlvJGxvd2VyQ0wpLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19ob3N0X3JhbmdlX2xpbmtfcmF0aW8kdXBwZXJDTCksCiAgYFZbYXV0aG9yc11gID0gYyhtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kc2lnbWEyLCBOQSksCiAgYFIyYCA9IGMocjJfaG9zdF9yYW5nZV9saW5rX3JhdGlvWzFdLCBOQSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDR9CiMgbmV3bW9kcyA8LSBzZXEoLTAuMywgMi4yLCBieSA9IDAuMSkKIyBwcmVkX2hvc3RfcmFuZ2VfbGlua19yYXRpbyA8LXByZWRpY3Qucm1hKG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbywgbmV3bW9kcyA9IG5ld21vZHMpIAojIHJpYmJvbl9kYXQgPC0gdGliYmxlKG5ld21vZHMgPSBuZXdtb2RzLCB5bWluID0gcHJlZF9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kY2kubGIsIHltYXggPSBwcmVkX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRjaS51YikKcHJlZF9ob3N0X3JhbmdlX2xpbmtfcmF0aW8gPC1wcmVkaWN0LnJtYShtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8pIAoKIyBwbG90dGluZwoKZmlnX2hvc3RfcmFuZ2VfbGlua19yYXRpbyA8LSAgZGF0ICU+JSAKICBmaWx0ZXIoIWlzLm5hKGhvc3RfcmFuZ2VfbGlua19yYXRpbykpICAlPiUgIyBnZXR0aW5nIHJpZGUgb2YgTkEgdmFsdWVzCiAgbXV0YXRlKHltaW4gPSBwcmVkX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRjaS5sYiwgCiAgICAgICAgIHltYXggPSBwcmVkX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRjaS51YiwKICAgICAgICAgeW1pbjIgPSBwcmVkX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRjci5sYiwKICAgICAgICAgeW1heDIgPSBwcmVkX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRjci51YiwKICAgICAgICAgcHJlZCA9IHByZWRfaG9zdF9yYW5nZV9saW5rX3JhdGlvJHByZWQpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKSwgeSA9IFpyLCBzaXplID0gKDEvVlpyKSArIDMsICkpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGZpbGwgPSAiZ3JleTkwIikgKwogICNnZW9tX3JpYmJvbihhZXMoeW1pbiA9IHltaW4sIHltYXggPSB5bWF4KSwgZmlsbCA9ICIjMDA3MkIyIikgICsgIyBub3QgcXVpdGUgc3VyZSB3aHkgdGhpcyBkb2VzIG5vdCB3b3JrCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluMiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAgImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9ICIjMDA3MkIyIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1heDIpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9ICIjMDA3MkIyIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1pbiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLGx0eSA9ICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSIjRDU1RTAwIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1heCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSIjRDU1RTAwIikgKyAKICBnZW9tX3Ntb290aChhZXMoeSA9IHByZWQpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0iZGFzaGVkIiwgbHdkID0gMC41LCBjb2xvdXIgPSJibGFjayIpICsgIAogIHlsaW0oLTEsIDIpICsgeGxpbSgtMC4wNSwgMikgKwogICNnZW9tX2FibGluZShpbnRlcmNlcHQgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMV1dLCBzbG9wZSA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1syXV0sIGFscGhhID0gMC43LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMC41KSArCiAgbGFicyh4ID0gImxuKHJhbmdlIGxpbmsgcmF0aW8pIiwgeSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKFpyKSwgIiAoZWZmZWN0IHNpemUpIikpLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcykiKSkpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgIyB0aGVtc2VzCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDEsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZmlnX2hvc3RfcmFuZ2VfbGlua19yYXRpbwpgYGAKCioqU3VwcGxlbWVudGFyeSBGaWd1cmUgMToqKgoKCiMjIyBUZXN0aW5nIHNwZWNpYWxpemF0aW9uIDI6IHRheG9taWMgYnJlYWR0aAoKYGBge3J9CiMgbWV0YS1yZWdyZXNzaW9uCm1yX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGggPC0gcm1hLm12KHlpID0gWnIsIFYgPSBWWnIsIG1vZHMgPSB+IGxvZyhob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoKSwgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgZGF0YSA9IGRhdCkKCmBgYAoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDM6KioKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhhbXBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBzeW1iaW9udF90YXhfYnJvYWRgLiAKYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoIDwtIFIyKG1yX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpCgojIGdldHRpbmcgZXN0aW1hdGVzOiBuYW1lIGRvZXMgbm90IHdvcmsgZm9yIHNsb3BlcwpyZXNfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCA8LSBnZXRfZXN0KG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbywgbW9kID0gImxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pIikKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKCJJbnRlcmNlcHQiLCAibG9nKGhvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpIiksCiAgRXN0aW1hdGUgPSBjKHJlc19ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoJGVzdGltYXRlKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoJGxvd2VyQ0wpLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoJHVwcGVyQ0wpLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRzaWdtYTIsIE5BKSwKICBgUjJgID0gYyhyMl9ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoWzFdLCBOQSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDR9CnByZWRfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCA8LXByZWRpY3Qucm1hKG1yX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpIAoKIyBwbG90dGluZwoKZmlnX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGggPC0gIGRhdCAlPiUgCiAgZmlsdGVyKCFpcy5uYShob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoKSkgICU+JSAjIGdldHRpbmcgcmlkZSBvZiBOQSB2YWx1ZXMKICBtdXRhdGUoeW1pbiA9IHByZWRfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRjaS5sYiwgCiAgICAgICAgIHltYXggPSBwcmVkX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgkY2kudWIsCiAgICAgICAgIHltaW4yID0gcHJlZF9ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoJGNyLmxiLAogICAgICAgICB5bWF4MiA9IHByZWRfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRjci51YiwKICAgICAgICAgcHJlZCA9IHByZWRfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRwcmVkKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbG9nKGhvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpLCB5ID0gWnIsIHNpemUgPSAoMS9WWnIpICsgMywgKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZmlsbCA9ICJncmV5OTAiKSArCiAgI2dlb21fcmliYm9uKGFlcyh5bWluID0geW1pbiwgeW1heCA9IHltYXgpLCBmaWxsID0gIiMwMDcyQjIiKSAgKyAjIG5vdCBxdWl0ZSBzdXJlIHdoeSB0aGlzIGRvZXMgbm90IHdvcmsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltaW4yKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ICAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4MiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4KSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArIAogIGdlb21fc21vb3RoKGFlcyh5ID0gcHJlZCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkYXNoZWQiLCBsd2QgPSAwLjUsIGNvbG91ciA9ImJsYWNrIikgKyAgCiAgeWxpbSgtMSwgMikgKyB4bGltKDAsIDEuNSkgKwogICNnZW9tX2FibGluZShpbnRlcmNlcHQgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMV1dLCBzbG9wZSA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1syXV0sIGFscGhhID0gMC43LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMC41KSArCiAgbGFicyh4ID0gImxuKHJhbmdlIGxpbmsgcmF0aW8pIiwgeSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKFpyKSwgIiAoZWZmZWN0IHNpemUpIikpLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcykiKSkpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgIyB0aGVtc2VzCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDEsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZmlnX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgKYGBgCgoqKlN1cHBsZW1lbnRhcnkgRmlndXJlIDI6KioKCmBgYHtyfQojIHJlb3JkZXJpbmcKZGF0JGVuZG9fb3JfZWN0byA8LSBmYWN0b3IoZGF0JGVuZG9fb3JfZWN0bywgbGV2ZWxzID0gYygiRW5kby9FY3RvIiwgIkVuZG8iLCAiRWN0byIpKQoKIyBtZXRhLXJlZ3Jlc3Npb246IG11dGlwbGUgaW50ZXJjZXB0cwptcl9lbmRvX29yX2VjdG8xIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBlbmRvX29yX2VjdG8gLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMQptcl9lbmRvX29yX2VjdG8yIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBlbmRvX29yX2VjdG8sIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdCAyCm1yX2VuZG9fb3JfZWN0bzMgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoZW5kb19vcl9lY3RvLCByZWYgPSAiRW5kbyIpLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgpgYGAKCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgZW5kb19vcl9lY3RvYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfZW5kb19vcl9lY3RvMSA8LSBSMihtcl9lbmRvX29yX2VjdG8xKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfZW5kb19vcl9lY3RvMSA8LSBnZXRfZXN0KG1yX2VuZG9fb3JfZWN0bzEsIG1vZCA9ICJlbmRvX29yX2VjdG8iKQpyZXNfZW5kb19vcl9lY3RvMiA8LSBnZXRfZXN0KG1yX2VuZG9fb3JfZWN0bzIsIG1vZCA9ICJlbmRvX29yX2VjdG8iKQpyZXNfZW5kb19vcl9lY3RvMyA8LSBnZXRfZXN0KG1yX2VuZG9fb3JfZWN0bzMsIG1vZCA9ICJlbmRvX29yX2VjdG8iKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoYXMuY2hhcmFjdGVyKHJlc19lbmRvX29yX2VjdG8xJG5hbWUpLCBjb250X2dlbihyZXNfZW5kb19vcl9lY3RvMSRuYW1lKSksCiAgRXN0aW1hdGUgPSBjKHJlc19lbmRvX29yX2VjdG8xJGVzdGltYXRlLCByZXNfZW5kb19vcl9lY3RvMiRlc3RpbWF0ZVstMV0sICByZXNfZW5kb19vcl9lY3RvMyRlc3RpbWF0ZVstKDE6MildKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19lbmRvX29yX2VjdG8xJGxvd2VyQ0wsIHJlc19lbmRvX29yX2VjdG8yJGxvd2VyQ0xbLTFdLCByZXNfZW5kb19vcl9lY3RvMyRsb3dlckNMWy0oMToyKV0pLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19lbmRvX29yX2VjdG8xJHVwcGVyQ0wsIHJlc19lbmRvX29yX2VjdG8yJHVwcGVyQ0xbLTFdLCByZXNfZW5kb19vcl9lY3RvMyR1cHBlckNMWy0oMToyKV0pLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfZW5kb19vcl9lY3RvMSRzaWdtYTIsICByZXAoTkEsIDUpKSwKICBgUjJgID0gYyhyMl9lbmRvX29yX2VjdG8xWzFdLCByZXAoTkEsIDUpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDR9CiMgYWRkaW5nIHNhbXBsZSBzaXplIChrKSBmb3IgZWFjaCBjYXRlZ29yeQprX2VuZG9fb3JfZWN0byA8LSBkYXQgJT4lIGdyb3VwX2J5KGVuZG9fb3JfZWN0bykgJT4lIGNvdW50KCkKIyBnZXR0aW5nIGVzdGltYXRlcyBhbmQgcHJlZGljaXRvbnMKcHJlZF9lbmRvX29yX2VjdG8gPC0gZ2V0X3ByZWQobXJfZW5kb19vcl9lY3RvMSwgbW9kID0gImVuZG9fb3JfZWN0byIpIApyZXNfZW5kb19vcl9lY3RvMSA8LSBsZWZ0X2pvaW4ocmVzX2VuZG9fb3JfZWN0bzEsIGtfZW5kb19vcl9lY3RvLCBieSA9ICBjKCJuYW1lIiA9ICJlbmRvX29yX2VjdG8iKSkgICU+JSBsZWZ0X2pvaW4ocHJlZF9lbmRvX29yX2VjdG8pCiNyZXNfc3ltYmlvc2lzMSAKIyBkcmF3aW5nIGEgZnVubmVsIHBsb3QgLSBmaWcgMmIKZmlnX2VuZG9fb3JfZWN0byA8LSBnZ3Bsb3QoZGF0YSA9IHJlc19lbmRvX29yX2VjdG8xLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoZW5kb19vcl9lY3RvKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gZW5kb19vcl9lY3RvLCBzaXplID0gKCgxL1ZacikgKyAzKSwgY29sb3VyID0gZW5kb19vcl9lY3RvKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC40KSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiRW5kby9FY3RvIiA9ICIjMDA3MkIyIiwgICJFbmRvIiA9ICIjRDU1RTAwIiwgICJFY3RvIj0gIiNDQzc5QTciKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkVuZG8vRWN0byIgPSAiIzAwNzJCMiIsICAiRW5kbyIgPSAiI0Q1NUUwMCIsICAiRWN0byI9ICIjQ0M3OUE3IikpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIkVuZG8vRWN0byIgPSAiQm90aCIsICAiRW5kbyIgPSAiRW5kb3N5bWJpb3NpcyIsICAiRWN0byI9ICJFY3Rvc3ltYmlvc2lzIikpICsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAtMSwgeSA9IHJlc19lbmRvX29yX2VjdG8xJG5hbWUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfZW5kb19vcl9lY3RvMSRuKSwgcGFyc2U9VFJVRSwgaGp1c3QgPSAibGVmdCIsIHNpemU9My41KSArCiAgbGFicyh4ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMociksICIgKGNvcnJlbGF0b24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzKSIpKSApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIpICsKICAjdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKSArCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ImJsYWNrIiwgaGp1c3QgPSAwLjUsIGFuZ2xlID0gOTApKSAKCmZpZ19lbmRvX29yX2VjdG8KYGBgCgoqKkZpZ3VyZSAyZzoqKiBUaGUgZWZmZWN0IFhYWFhYWAoKCiMjIyBUaGUgZWZmZWN0IG9mIHRoZSBtb2RlbCBvZiB0cmFuc21pc3Npb24KCmBgYHtyfQojIG1ldGEtcmVncmVzc2lvbjogbXV0aXBsZSBpbnRlcmNlcHRzCm1yX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMQptcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMgptcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQsIHJlZiA9ICJ2ZXJ0aWNhbCIpLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCmBgYAoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDM6KioKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhhbXBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZGAuIApgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSA8LSBSMihtcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEpCgojIGdldHRpbmcgZXN0aW1hdGVzCnJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEgPC0gZ2V0X2VzdChtcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEsIG1vZCA9ICJtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCIpCnJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIgPC0gZ2V0X2VzdChtcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIsIG1vZCA9ICJtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCIpCnJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMgPC0gZ2V0X2VzdChtcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMsIG1vZCA9ICJtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCIpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRuYW1lKSwgY29udF9nZW4ocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRuYW1lKSksCiAgRXN0aW1hdGUgPSBjKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkZXN0aW1hdGUsIHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIkZXN0aW1hdGVbLTFdLCAgcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMyRlc3RpbWF0ZVstKDE6MildKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkbG93ZXJDTCwgcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMiRsb3dlckNMWy0xXSwgcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMyRsb3dlckNMWy0oMToyKV0pLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkdXBwZXJDTCwgcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMiR1cHBlckNMWy0xXSwgcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMyR1cHBlckNMWy0oMToyKV0pLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxJHNpZ21hMiwgIHJlcChOQSwgNSkpLAogIGBSMmAgPSBjKHIyX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMVsxXSwgcmVwKE5BLCA1KSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgCmBgYAoKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSAzLjV9CiMgYWRkaW5nIHNhbXBsZSBzaXplIChrKSBmb3IgZWFjaCBjYXRlZ29yeQprX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkIDwtIGRhdCAlPiUgZ3JvdXBfYnkobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQpICU+JSBjb3VudCgpCiMgZ2V0dGluZyBlc3RpbWF0ZXMgYW5kIHByZWRpY2l0b25zCnByZWRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPC0gZ2V0X3ByZWQobXJfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxLCBtb2QgPSAibW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQiKSAKcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSA8LSBsZWZ0X2pvaW4ocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSwga19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCwgYnkgPSAgYygibmFtZSIgPSAibW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQiKSkgICU+JSBsZWZ0X2pvaW4ocHJlZF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCkKI3Jlc19zeW1iaW9zaXMxIAojIGRyYXdpbmcgYSBmdW5uZWwgcGxvdCAtIGZpZyAyYgpmaWdfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPC0gZ2dwbG90KGRhdGEgPSByZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQpKSwgCiAgICAgICAgICAgICAgICAgICBhZXMoeD0gdGFuaChaciksIHkgPSBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCwgc2l6ZSA9ICgoMS9WWnIpICsgMyksIGNvbG91ciA9IG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC40KSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYm90aCIgPSAiIzAwNzJCMiIsICAiaG9yaXpvbnRhbCIgPSAiI0Q1NUUwMCIsICAidmVydGljYWwiPSAiI0NDNzlBNyIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYm90aCIgPSAiIzAwNzJCMiIsICAiaG9yaXpvbnRhbCIgPSAiI0Q1NUUwMCIsICAidmVydGljYWwiPSAiI0NDNzlBNyIpKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHMgPSBjKCJib3RoIiA9ICJCb3RoIiwgICJob3Jpem9udGFsIiA9ICJIb3Jpem9udGFsIiwgICJ2ZXJ0aWNhbCI9ICJWZXJ0aWNhbCIpKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gLTEsIHkgPSByZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxJG5hbWUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMpIikpICkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZmlnX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkCmBgYAoKKipGaWd1cmUgMmc6KiogVGhlIGVmZmVjdCBYWFhYWFgKCgojIyMgVGhlIGNvbWJpbmVkIGVmZmVjdCBvZiBzeW1iaW9zaXMgYW5kIG1vZGUgb2YgdHJhbnNtaXNzaW9uCgpgYGB7cn0KIyByZW9yZGVyaW5nCmRhdCRzeW1iaW9zaXNfdHJhbnNtaXNzaW9uIDwtIGZhY3RvcihkYXQkc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTXV0dWFsaXN0Ym90aCIsICJNdXR1YWxpc3Rob3Jpem9udGFsIiwiTXV0dWFsaXN0dmVydGljYWwiLCAiUGFyYXNpdGVib3RoIiwgIlBhcmFzaXRlaG9yaXpvbnRhbCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk11dHVhbGlzdEJvdGgiLCAiTXV0dWFsaXN0SG9yaXpvbnRhbCIsIk11dHVhbGlzdFZlcnRpY2FsIiwgIlBhcmFzaXRlQm90aCIsICJQYXJhc2l0ZUhvcml6b250YWwiKSkKCiMgbWV0YS1yZWdyZXNzaW9uOiBtdXRpcGxlIGludGVyY2VwdHMKbXJfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHN5bWJpb3Npc190cmFuc21pc3Npb24gLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojICMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdHMgeCAxMAojIGdldHRpbmcgdGhlIGxldmVsIG5hbWVzIG91dApsZXZlbF9uYW1lcyA8LSBsZXZlbHMoZGF0JHN5bWJpb3Npc190cmFuc21pc3Npb24pCgojIGhlbHBlciBmdW5jdGlvbiB0byBydW4gbWV0YWZvciBtZXRhLXJlZ3Jlc3Npb24KcnVuX3JtYSA8LSBmdW5jdGlvbihuYW1lKSB7CiAgcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwgcmVmID0gbmFtZSksIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKfQoKIyByZXN1bHRzIG9mIG1ldGEtcmVncmVzc2lvbiBpbmNsdWRpbmcgYWxsIGNvbnRyYXN0IHJlc3VsdHM7IHRha2luZyB0aGUgbGFzdCBsZXZlbCBvdXQgKFstbGVuZ3RoKGxldmVsX25hbWVzKV0pCm1yX3N5bWJpb3Npc190cmFuc21pc3Npb24gPC0gbWFwKGxldmVsX25hbWVzWy1sZW5ndGgobGV2ZWxfbmFtZXMpXSwgcnVuX3JtYSkKCmBgYAoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDM6KioKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhhbXBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBob3N0X3RheF9icm9hZGAuIApgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX3N5bWJpb3Npc190cmFuc21pc3Npb24xIDwtIFIyKG1yX3N5bWJpb3Npc190cmFuc21pc3Npb24xKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEgPC0gZ2V0X2VzdChtcl9zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSwgbW9kID0gInN5bWJpb3Npc190cmFuc21pc3Npb24iKQpyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiA8LSBtYXAobXJfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwgfiBnZXRfZXN0KC54LCBtb2QgPSAic3ltYmlvc2lzX3RyYW5zbWlzc2lvbiIpKQoKIyBhIGxpc3Qgb2YgdGhlIG51bWJlcnMgdG8gdGFrZSBvdXQgdW5uZWNlc3NhcnkgY29udHJhc3RzCmNvbnRyYV9saXN0IDwtIE1hcChzZXEsIGZyb209MSwgdG89MTo0KQoKIyB5b3UgbmVlZCB0byBmbGF0dGVuIHR3aWNlOiBmaXJzdCB0byBtYWtlIGl0IGEgbGlzdCBhbmQgbWFrZSBpdCBhIHZlY3Rvcgplc3RpYW10ZXMgPC0gbWFwMihyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwgY29udHJhX2xpc3QsIH4ueFstKC55KSwiZXN0aW1hdGUiXSkgJT4lIGZsYXR0ZW4oKSAlPiUgZmxhdHRlbl9kYmwoKQpsb3dlckNMcyA8LSBtYXAyKHJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uLCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJsb3dlckNMIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKdXBwZXJDTHMgPC0gbWFwMihyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwgY29udHJhX2xpc3QsIH4ueFstKC55KSwidXBwZXJDTCJdKSAlPiUgZmxhdHRlbigpICU+JSBmbGF0dGVuX2RibCgpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xJG5hbWUpLCBjb250X2dlbihyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEkbmFtZSkpLAogIEVzdGltYXRlID0gYyhyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEkZXN0aW1hdGUsIGVzdGlhbXRlcyksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEkbG93ZXJDTCxsb3dlckNMcyksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xJHVwcGVyQ0wsbG93ZXJDTHMpLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEkc2lnbWEyLCAgcmVwKE5BLCAoNSArIGNob29zZSg1LDIpKS0gMSkpLAogIGBSMmAgPSBjKHIyX3N5bWJpb3Npc190cmFuc21pc3Npb24xWzFdLCByZXAoTkEsICg1ICsgY2hvb3NlKDUsIDIpKS0gMSkpKSAlPiUga2FibGUoImh0bWwiLCAgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAlPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiMzAwcHgiKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0gNX0KIyBjb2xvdXIgbGlzdApjb2xvdXJfbHMgPC0gYygiIzAwMDAwMCIsICIjRTY5RjAwIiwgIiM1NkI0RTkiLCAiIzAwOUU3MyIsICAiI0YwRTQyMiIsICAiIzAwNzJCMiIsICAiI0Q1NUUwMCIsICIjQ0M3OUE3IiwgIiMwMDAwOEIiLCAiIzhCMEE1MCIsICIjNTRGRjlGIiwgIiM5OTk5OTkiKQoKIyBhZGRpbmcgc2FtcGxlIHNpemUgKGspIGZvciBlYWNoIGNhdGVnb3J5Cmtfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiA8LSBkYXQgJT4lIGdyb3VwX2J5KHN5bWJpb3Npc190cmFuc21pc3Npb24pICU+JSBjb3VudCgpCiMgZ2V0dGluZyBlc3RpbWF0ZXMgYW5kIHByZWRpY2l0b25zCnByZWRfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiA8LSBnZXRfcHJlZChtcl9zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSwgbW9kID0gInN5bWJpb3Npc190cmFuc21pc3Npb24iKSAKcmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xIDwtIGxlZnRfam9pbihyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEsIGtfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwgYnkgPSAgYygibmFtZSIgPSAic3ltYmlvc2lzX3RyYW5zbWlzc2lvbiIpKSAgJT4lIGxlZnRfam9pbihwcmVkX3N5bWJpb3Npc190cmFuc21pc3Npb24pCiNyZXNfc3ltYmlvc2lzMSAKIyBkcmF3aW5nIGEgZnVubmVsIHBsb3QgLSBmaWcgMmIKZmlnX3N5bWJpb3Npc190cmFuc21pc3Npb24gPC0gZ2dwbG90KGRhdGEgPSByZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEsIGFlcyh4ID0gdGFuaChlc3RpbWF0ZSksIHkgPSBuYW1lKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtMSwgMSksIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpICkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdCAlPiUgZmlsdGVyKCFpcy5uYShzeW1iaW9zaXNfdHJhbnNtaXNzaW9uKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwgc2l6ZSA9ICgoMS9WWnIpICsgMyksIGNvbG91ciA9IHN5bWJpb3Npc190cmFuc21pc3Npb24pLCBncm91cE9uWCA9IEZBTFNFLCBhbHBoYT0wLjQpICsgCiAgIyA5NSAlcHJlY2l0aW9uIGludGVydmFsIChQSSkKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJQUiksIHhtYXggPSB0YW5oKHVwcGVyUFIpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjYpICsKICAjIDk1ICVDSQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlckNMKSwgeG1heCA9IHRhbmgodXBwZXJDTCkpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMS4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogICMgY3JlYXRpbmcgZG90cyBhbmQgZGlmZmVyZW50IHNpemUgKGJlZS1zd2FybSBhbmQgYnViYmxlcykKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gbmFtZSksIHNpemUgPSAzLCBzaGFwZSA9IDIxKSArICMKICAjIHNldHRpbmcgY29sb3VycwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgIGMoIk11dHVhbGlzdEJvdGgiPSBjb2xvdXJfbHNbMV0sICJNdXR1YWxpc3RIb3Jpem9udGFsIj0gY29sb3VyX2xzWzJdLCAiTXV0dWFsaXN0VmVydGljYWwiID0gY29sb3VyX2xzWzNdLCJQYXJhc2l0ZUJvdGgiPSBjb2xvdXJfbHNbNF0sICJQYXJhc2l0ZUhvcml6b250YWwiID0gY29sb3VyX2xzWzVdKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk11dHVhbGlzdEJvdGgiPSBjb2xvdXJfbHNbMV0sICJNdXR1YWxpc3RIb3Jpem9udGFsIj0gY29sb3VyX2xzWzJdLCAiTXV0dWFsaXN0VmVydGljYWwiID0gY29sb3VyX2xzWzNdLCJQYXJhc2l0ZUJvdGgiPSBjb2xvdXJfbHNbNF0sICJQYXJhc2l0ZUhvcml6b250YWwiID0gY29sb3VyX2xzWzVdKSkgKwogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gYygiTXV0dWFsaXN0Qm90aCIgPSAiTXV0dWFsaXN0LVxuQm90aCIsICJNdXR1YWxpc3RIb3Jpem9udGFsIiA9ICJNdXR1YWxpc3QtXG5Ib3Jpem9udGFsIiwiTXV0dWFsaXN0VmVydGljYWwiID0gIk11dHVhbGlzdC1cblZlcnRpY2FsIiwgIlBhcmFzaXRlQm90aCIgPSAiUGFyYXNpdGUtXG5Cb3RoIiwgIlBhcmFzaXRlSG9yaXpvbnRhbCIgPSAiUGFyYXNpdGUtXG5Ib3Jpem9udGFsIikpICsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAtMSwgeSA9IHJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSRuYW1lLCBsYWJlbD0gcGFzdGUoIml0YWxpYyhrKT09IiwgcmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMpIikpICkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIpICsKICAjdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKSArCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ImJsYWNrIiwgaGp1c3QgPSAwLjUsIGFuZ2xlID0gOTApKSAKCmZpZ19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uCmBgYAoKTk9URSEhIQoqIERvIHRoZSBSRUYgUkVGIFJFRiAKKiBKdXN0aWZpY2F0aW9uIG9mIHRoZSB1c2Ugb2YgY29tYmluZWQgZGF0YXNldHMuLi4uIC0gZG9uZQoqIGp1c3QgZG8gdGhlIG1haW4gb25lIGZvciBhbGwgdGhyZWUgZGF0YXNldHMgYnV0IG5vdCBvdGhlcnMKKiBvciB3ZSBjb3VsZCAtIHByb3ZpZGUgZm9yZXN0IHBsb3RzIG9mIGFsbCB0aGUgdGhyZWUgZGF0YXNldHM/Pz8/IChkbyBpdCBsYXRlcikKKiBoZXRlcm9nZW5laXR5IC0gZG9uZSAKCgoKCgoqIG9uZS1ieS1vbmUgYW5hbHlzZXMgaGVyZS4uLgoKIyMjIFRoZSBjb21iaW5lZCBlZmZlY3Qgb2YgaG9zdCB0YXhhIGFuZCBzeW1iaW9zaXMgKHBhcmFzaXRpc20gdnMuIG11dHVhbGlzbSkKCmBgYHtyfQojIHJlb3JkZXJpbmcKZGF0JGhvc3RfdGF4X3N5bWJpb3NpcyA8LSBmYWN0b3IoZGF0JGhvc3RfdGF4X3N5bWJpb3NpcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIk1pY3JvYmVNdXR1YWxpc3QiLCAiTWljcm9iZVBhcmFzaXRlIiwgICJQbGFudE11dHVhbGlzdCIsICJQbGFudFBhcmFzaXRlIiwgIkludmVydE11dHVhbGlzdCIsICAiSW52ZXJ0UGFyYXNpdGUiLCAgIlZlcnRNdXR1YWxpc3QiLCAiVmVydFBhcmFzaXRlIikpCgojIG1ldGEtcmVncmVzc2lvbjogbXV0aXBsZSBpbnRlcmNlcHRzCm1yX2hvc3RfdGF4X3N5bWJpb3NpczEgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IGhvc3RfdGF4X3N5bWJpb3NpcyAtIDEsIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0cyB4IDEwCiMgZ2V0dGluZyB0aGUgbGV2ZWwgbmFtZXMgb3V0CmxldmVsX25hbWVzIDwtIGxldmVscyhkYXQkaG9zdF90YXhfc3ltYmlvc2lzKQoKIyBoZWxwZXIgZnVuY3Rpb24gdG8gcnVuIG1ldGFmb3IgbWV0YS1yZWdyZXNzaW9uCnJ1bl9ybWEgPC0gZnVuY3Rpb24obmFtZSkgewogIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiByZWxldmVsKGhvc3RfdGF4X3N5bWJpb3NpcywgcmVmID0gbmFtZSksIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKfQoKIyByZXN1bHRzIG9mIG1ldGEtcmVncmVzc2lvbiBpbmNsdWRpbmcgYWxsIGNvbnRyYXN0IHJlc3VsdHM7IHRha2luZyB0aGUgbGFzdCBsZXZlbCBvdXQgKFstbGVuZ3RoKGxldmVsX25hbWVzKV0pCm1yX2hvc3RfdGF4X3N5bWJpb3NpcyA8LSBtYXAobGV2ZWxfbmFtZXNbLWxlbmd0aChsZXZlbF9uYW1lcyldLCBydW5fcm1hKQoKYGBgCgoqKlN1cHBsZW1lbnRhcnkgVGFibGUgMzoqKgpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleGFtcGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYGhvc3RfdGF4X2Jyb2FkYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfaG9zdF90YXhfc3ltYmlvc2lzMSA8LSBSMihtcl9ob3N0X3RheF9zeW1iaW9zaXMxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfaG9zdF90YXhfc3ltYmlvc2lzMSA8LSBnZXRfZXN0KG1yX2hvc3RfdGF4X3N5bWJpb3NpczEsIG1vZCA9ICJob3N0X3RheF9zeW1iaW9zaXMiKQpyZXNfaG9zdF90YXhfc3ltYmlvc2lzIDwtIG1hcChtcl9ob3N0X3RheF9zeW1iaW9zaXMsIH4gZ2V0X2VzdCgueCwgbW9kID0gImhvc3RfdGF4X3N5bWJpb3NpcyIpKQoKIyBhIGxpc3Qgb2YgdGhlIG51bWJlcnMgdG8gdGFrZSBvdXQgdW5uZWNlc3NhcnkgY29udHJhc3RzCmNvbnRyYV9saXN0IDwtIE1hcChzZXEsIGZyb209MSwgdG89MTo3KQoKIyB5b3UgbmVlZCB0byBmbGF0dGVuIHR3aWNlOiBmaXJzdCB0byBtYWtlIGl0IGEgbGlzdCBhbmQgbWFrZSBpdCBhIHZlY3Rvcgplc3RpYW10ZXMgPC0gbWFwMihyZXNfaG9zdF90YXhfc3ltYmlvc2lzLCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJlc3RpbWF0ZSJdKSAlPiUgZmxhdHRlbigpICU+JSBmbGF0dGVuX2RibCgpCmxvd2VyQ0xzIDwtIG1hcDIocmVzX2hvc3RfdGF4X3N5bWJpb3NpcywgY29udHJhX2xpc3QsIH4ueFstKC55KSwibG93ZXJDTCJdKSAlPiUgZmxhdHRlbigpICU+JSBmbGF0dGVuX2RibCgpCnVwcGVyQ0xzIDwtIG1hcDIocmVzX2hvc3RfdGF4X3N5bWJpb3NpcywgY29udHJhX2xpc3QsIH4ueFstKC55KSwidXBwZXJDTCJdKSAlPiUgZmxhdHRlbigpICU+JSBmbGF0dGVuX2RibCgpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX2hvc3RfdGF4X3N5bWJpb3NpczEkbmFtZSksIGNvbnRfZ2VuKHJlc19ob3N0X3RheF9zeW1iaW9zaXMxJG5hbWUpKSwKICBFc3RpbWF0ZSA9IGMocmVzX2hvc3RfdGF4X3N5bWJpb3NpczEkZXN0aW1hdGUsIGVzdGlhbXRlcyksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhyZXNfaG9zdF90YXhfc3ltYmlvc2lzMSRsb3dlckNMLGxvd2VyQ0xzKSwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gYyhyZXNfaG9zdF90YXhfc3ltYmlvc2lzMSR1cHBlckNMLGxvd2VyQ0xzKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX2hvc3RfdGF4X3N5bWJpb3NpczEkc2lnbWEyLCAgcmVwKE5BLCAoOCArIGNob29zZSg4LDIpKS0gMSkpLAogIGBSMmAgPSBjKHIyX2hvc3RfdGF4X3N5bWJpb3NpczFbMV0sIHJlcChOQSwgKDggKyBjaG9vc2UoOCwgMikpLSAxKSkpICU+JSBrYWJsZSgiaHRtbCIsICBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIzMDBweCIpCmBgYAoKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSA4fQojIGFkZGluZyBzYW1wbGUgc2l6ZSAoaykgZm9yIGVhY2ggY2F0ZWdvcnkKa19ob3N0X3RheF9zeW1iaW9zaXMgPC0gZGF0ICU+JSBncm91cF9ieShob3N0X3RheF9zeW1iaW9zaXMpICU+JSBjb3VudCgpCiMgZ2V0dGluZyBlc3RpbWF0ZXMgYW5kIHByZWRpY2l0b25zCnByZWRfaG9zdF90YXhfc3ltYmlvc2lzIDwtIGdldF9wcmVkKG1yX2hvc3RfdGF4X3N5bWJpb3NpczEsIG1vZCA9ICJob3N0X3RheF9zeW1iaW9zaXMiKSAKcmVzX2hvc3RfdGF4X3N5bWJpb3NpczEgPC0gbGVmdF9qb2luKHJlc19ob3N0X3RheF9zeW1iaW9zaXMxLCBrX2hvc3RfdGF4X3N5bWJpb3NpcywgYnkgPSAgYygibmFtZSIgPSAiaG9zdF90YXhfc3ltYmlvc2lzIikpICAlPiUgbGVmdF9qb2luKHByZWRfaG9zdF90YXhfc3ltYmlvc2lzKQojcmVzX3N5bWJpb3NpczEgCiMgZHJhd2luZyBhIGZ1bm5lbCBwbG90IC0gZmlnIDJiCmZpZ19ob3N0X3RheF9zeW1iaW9zaXMgPC0gZ2dwbG90KGRhdGEgPSByZXNfaG9zdF90YXhfc3ltYmlvc2lzMSwgYWVzKHggPSB0YW5oKGVzdGltYXRlKSwgeSA9IG5hbWUpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC0xLCAxKSwgYnJlYWtzID0gc2VxKC0xLCAxLCBieSA9IDAuMikgKSArCiAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0ICU+JSBmaWx0ZXIoIWlzLm5hKGhvc3RfdGF4X3N5bWJpb3NpcykpLCAKICAgICAgICAgICAgICAgICAgIGFlcyh4PSB0YW5oKFpyKSwgeSA9IGhvc3RfdGF4X3N5bWJpb3Npcywgc2l6ZSA9ICgoMS9WWnIpICsgMyksIGNvbG91ciA9IGhvc3RfdGF4X3N5bWJpb3NpcyksIGdyb3VwT25YID0gRkFMU0UsIGFscGhhPTAuNCkgKyAKICAjIDk1ICVwcmVjaXRpb24gaW50ZXJ2YWwgKFBJKQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlclBSKSwgeG1heCA9IHRhbmgodXBwZXJQUikpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMC41LCBhbHBoYSA9IDAuNikgKwogICMgOTUgJUNJCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyQ0wpLCB4bWF4ID0gdGFuaCh1cHBlckNMKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAxLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJibGFjayIsIGFscGhhID0gMC4zKSArCiAgIyBjcmVhdGluZyBkb3RzIGFuZCBkaWZmZXJlbnQgc2l6ZSAoYmVlLXN3YXJtIGFuZCBidWJibGVzKQogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBuYW1lKSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEpICsgIwogICMgc2V0dGluZyBjb2xvdXJzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9ICAgYygiTWljcm9iZU11dHVhbGlzdCI9IGNvbG91cl9sc1sxXSwgIk1pY3JvYmVQYXJhc2l0ZSI9IGNvbG91cl9sc1syXSwgICJQbGFudE11dHVhbGlzdCI9IGNvbG91cl9sc1szXSwgIlBsYW50UGFyYXNpdGUiPSBjb2xvdXJfbHNbNF0sICJJbnZlcnRNdXR1YWxpc3QiID0gY29sb3VyX2xzWzVdLCAgIkludmVydFBhcmFzaXRlIj0gY29sb3VyX2xzWzZdLCAiVmVydE11dHVhbGlzdCI9IGNvbG91cl9sc1s3XSwgICAgICJWZXJ0UGFyYXNpdGUiPSBjb2xvdXJfbHNbOF0gKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk1pY3JvYmVNdXR1YWxpc3QiPSBjb2xvdXJfbHNbMV0sICJNaWNyb2JlUGFyYXNpdGUiPSBjb2xvdXJfbHNbMl0sICAiUGxhbnRNdXR1YWxpc3QiPSBjb2xvdXJfbHNbM10sICJQbGFudFBhcmFzaXRlIj0gY29sb3VyX2xzWzRdLCAiSW52ZXJ0TXV0dWFsaXN0IiA9IGNvbG91cl9sc1s1XSwgICJJbnZlcnRQYXJhc2l0ZSI9IGNvbG91cl9sc1s2XSwgIlZlcnRNdXR1YWxpc3QiPSBjb2xvdXJfbHNbN10sICAgICAiVmVydFBhcmFzaXRlIj0gY29sb3VyX2xzWzhdICkpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIk1pY3JvYmVNdXR1YWxpc3QiPSAiTWljcm9iZS1cbk11dHVhbGlzdCIsICJNaWNyb2JlUGFyYXNpdGUiPSAiTWljcm9iZS1cblBhcmFzaXRlIiwgICJQbGFudE11dHVhbGlzdCIgPSAiUGxhbnQtXG5NdXR1YWxpc3QiLCAiUGxhbnRQYXJhc2l0ZSI9IlBsYW50LVxuUGFyYXNpdGUiLCAiSW52ZXJ0TXV0dWFsaXN0IiA9ICJJbnZlcnRlYnJhdGUtXG5NdXR1YWxpc3QiLCAgICJJbnZlcnRQYXJhc2l0ZSI9ICJJbnZlcnRlYnJhdGUtXG5QYXJhc2l0ZSIsICJWZXJ0TXV0dWFsaXN0Ij0gIlZlcnRlYnJhdGUtXG5NdXR1YWxpc3QiLCAgIlZlcnRQYXJhc2l0ZSI9ICJWZXJ0ZWJyYXRlLVxuUGFyYXNpdGUiICkpICsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAtMSwgeSA9IHJlc19ob3N0X3RheF9zeW1iaW9zaXMxJG5hbWUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfaG9zdF90YXhfc3ltYmlvc2lzMSRuKSwgcGFyc2U9VFJVRSwgaGp1c3QgPSAibGVmdCIsIHNpemU9My41KSArCiAgbGFicyh4ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMociksICIgKGNvcnJlbGF0b24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzKSIpKSApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgCgpmaWdfaG9zdF90YXhfc3ltYmlvc2lzCmBgYAoKKipTdXBwbGVtZW50YXJ5IEZpZ3VyZSAzOioqCgojIyMgVGhlIGNvbWJpbmVkIGVmZmVjdCBvZiBzeW1iaW9udCB0YXhhIGFuZCBzeW1iaW9zaXMgKHBhcmFzaXRpc20gdnMuIG11dHVhbGlzbSkKCk5PVEUgLSBzeW1iaW9udF90YXhfc3ltYmlvc2lzID0gMjEgY29tYmluYXRpb25zCgpgYGB7cn0KIyByZW9yZGVyaW5nCmRhdCRzeW1iaW9udF90YXhfc3ltYmlvc2lzIDwtIGZhY3RvcihkYXQkc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCAgIk1pY3JvYmVNdXR1YWxpc3QiLCAiTWljcm9iZVBhcmFzaXRlIiwgICJQbGFudE11dHVhbGlzdCIsICJQbGFudFBhcmFzaXRlIiwiSW52ZXJ0TXV0dWFsaXN0IiwgIkludmVydFBhcmFzaXRlIiwgIlZlcnRQYXJhc2l0ZSIpKQoKIyBtZXRhLXJlZ3Jlc3Npb246IG11bHRpcGxlIGludGVyY2VwdHMKbXJfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHN5bWJpb250X3RheF9zeW1iaW9zaXMgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojICMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdHMgeCAxMAojIGdldHRpbmcgdGhlIGxldmVsIG5hbWVzIG91dApsZXZlbF9uYW1lcyA8LSBsZXZlbHMoZGF0JHN5bWJpb250X3RheF9zeW1iaW9zaXMpCgojIGhlbHBlciBmdW5jdGlvbiB0byBydW4gbWV0YWZvciBtZXRhLXJlZ3Jlc3Npb24KcnVuX3JtYSA8LSBmdW5jdGlvbihuYW1lKSB7CiAgcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgcmVmID0gbmFtZSksIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKfQoKIyByZXN1bHRzIG9mIG1ldGEtcmVncmVzc2lvbiBpbmNsdWRpbmcgYWxsIGNvbnRyYXN0IHJlc3VsdHM7IHRha2luZyB0aGUgbGFzdCBsZXZlbCBvdXQgKFstbGVuZ3RoKGxldmVsX25hbWVzKV0pCm1yX3N5bWJpb250X3RheF9zeW1iaW9zaXMgPC0gbWFwKGxldmVsX25hbWVzWy1sZW5ndGgobGV2ZWxfbmFtZXMpXSwgcnVuX3JtYSkKCmBgYAoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDM6KioKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhhbXBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBob3N0X3RheF9icm9hZGAuIApgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX3N5bWJpb250X3RheF9zeW1iaW9zaXMxIDwtIFIyKG1yX3N5bWJpb250X3RheF9zeW1iaW9zaXMxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEgPC0gZ2V0X2VzdChtcl9zeW1iaW9udF90YXhfc3ltYmlvc2lzMSwgbW9kID0gInN5bWJpb250X3RheF9zeW1iaW9zaXMiKQpyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcyA8LSBtYXAobXJfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgfiBnZXRfZXN0KC54LCBtb2QgPSAic3ltYmlvbnRfdGF4X3N5bWJpb3NpcyIpKQoKIyBhIGxpc3Qgb2YgdGhlIG51bWJlcnMgdG8gdGFrZSBvdXQgdW5uZWNlc3NhcnkgY29udHJhc3RzCmNvbnRyYV9saXN0IDwtIE1hcChzZXEsIGZyb209MSwgdG89MTo2KQoKIyB5b3UgbmVlZCB0byBmbGF0dGVuIHR3aWNlOiBmaXJzdCB0byBtYWtlIGl0IGEgbGlzdCBhbmQgbWFrZSBpdCBhIHZlY3Rvcgplc3RpYW10ZXMgPC0gbWFwMihyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgY29udHJhX2xpc3QsIH4ueFstKC55KSwiZXN0aW1hdGUiXSkgJT4lIGZsYXR0ZW4oKSAlPiUgZmxhdHRlbl9kYmwoKQpsb3dlckNMcyA8LSBtYXAyKHJlc19zeW1iaW9udF90YXhfc3ltYmlvc2lzLCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJsb3dlckNMIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKdXBwZXJDTHMgPC0gbWFwMihyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgY29udHJhX2xpc3QsIH4ueFstKC55KSwidXBwZXJDTCJdKSAlPiUgZmxhdHRlbigpICU+JSBmbGF0dGVuX2RibCgpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX3N5bWJpb250X3RheF9zeW1iaW9zaXMxJG5hbWUpLCBjb250X2dlbihyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkbmFtZSkpLAogIEVzdGltYXRlID0gYyhyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkZXN0aW1hdGUsIGVzdGlhbXRlcyksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkbG93ZXJDTCxsb3dlckNMcyksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX3N5bWJpb250X3RheF9zeW1iaW9zaXMxJHVwcGVyQ0wsbG93ZXJDTHMpLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkc2lnbWEyLCAgcmVwKE5BLCAoNyArIGNob29zZSg3LDIpKS0gMSkpLAogIGBSMmAgPSBjKHIyX3N5bWJpb250X3RheF9zeW1iaW9zaXMxWzFdLCByZXAoTkEsICg3ICsgY2hvb3NlKDcsIDIpKS0gMSkpKSAlPiUga2FibGUoImh0bWwiLCAgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAlPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiMzAwcHgiKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0gN30KIyBhZGRpbmcgc2FtcGxlIHNpemUgKGspIGZvciBlYWNoIGNhdGVnb3J5Cmtfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcyA8LSBkYXQgJT4lIGdyb3VwX2J5KHN5bWJpb250X3RheF9zeW1iaW9zaXMpICU+JSBjb3VudCgpCiMgZ2V0dGluZyBlc3RpbWF0ZXMgYW5kIHByZWRpY2l0b25zCnByZWRfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcyA8LSBnZXRfcHJlZChtcl9zeW1iaW9udF90YXhfc3ltYmlvc2lzMSwgbW9kID0gInN5bWJpb250X3RheF9zeW1iaW9zaXMiKSAKcmVzX3N5bWJpb250X3RheF9zeW1iaW9zaXMxIDwtIGxlZnRfam9pbihyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEsIGtfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgYnkgPSAgYygibmFtZSIgPSAic3ltYmlvbnRfdGF4X3N5bWJpb3NpcyIpKSAgJT4lIGxlZnRfam9pbihwcmVkX3N5bWJpb250X3RheF9zeW1iaW9zaXMpCiNyZXNfc3ltYmlvc2lzMSAKIyBkcmF3aW5nIGEgZnVubmVsIHBsb3QgLSBmaWcgMmIKZmlnX3N5bWJpb250X3RheF9zeW1iaW9zaXMgPC0gZ2dwbG90KGRhdGEgPSByZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEsIGFlcyh4ID0gdGFuaChlc3RpbWF0ZSksIHkgPSBuYW1lKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtMSwgMSksIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpICkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdCAlPiUgZmlsdGVyKCFpcy5uYShzeW1iaW9udF90YXhfc3ltYmlvc2lzKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gc3ltYmlvbnRfdGF4X3N5bWJpb3Npcywgc2l6ZSA9ICgoMS9WWnIpICsgMyksIGNvbG91ciA9IHN5bWJpb250X3RheF9zeW1iaW9zaXMpLCBncm91cE9uWCA9IEZBTFNFLCBhbHBoYT0wLjQpICsgCiAgIyA5NSAlcHJlY2l0aW9uIGludGVydmFsIChQSSkKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJQUiksIHhtYXggPSB0YW5oKHVwcGVyUFIpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjYpICsKICAjIDk1ICVDSQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlckNMKSwgeG1heCA9IHRhbmgodXBwZXJDTCkpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMS4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogICMgY3JlYXRpbmcgZG90cyBhbmQgZGlmZmVyZW50IHNpemUgKGJlZS1zd2FybSBhbmQgYnViYmxlcykKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gbmFtZSksIHNpemUgPSAzLCBzaGFwZSA9IDIxKSArICMKICAjIHNldHRpbmcgY29sb3VycwogICMgc2V0dGluZyBjb2xvdXJzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9ICAgYygiTWljcm9iZU11dHVhbGlzdCI9IGNvbG91cl9sc1sxXSwgIk1pY3JvYmVQYXJhc2l0ZSI9IGNvbG91cl9sc1syXSwgICJQbGFudE11dHVhbGlzdCI9IGNvbG91cl9sc1szXSwgIlBsYW50UGFyYXNpdGUiPSBjb2xvdXJfbHNbNF0sICJJbnZlcnRNdXR1YWxpc3QiID0gY29sb3VyX2xzWzVdLCAgIkludmVydFBhcmFzaXRlIj0gY29sb3VyX2xzWzZdLCAiVmVydFBhcmFzaXRlIj0gY29sb3VyX2xzWzhdICkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNaWNyb2JlTXV0dWFsaXN0Ij0gY29sb3VyX2xzWzFdLCAiTWljcm9iZVBhcmFzaXRlIj0gY29sb3VyX2xzWzJdLCAgIlBsYW50TXV0dWFsaXN0Ij0gY29sb3VyX2xzWzNdLCAiUGxhbnRQYXJhc2l0ZSI9IGNvbG91cl9sc1s0XSwgIkludmVydE11dHVhbGlzdCIgPSBjb2xvdXJfbHNbNV0sICAiSW52ZXJ0UGFyYXNpdGUiPSBjb2xvdXJfbHNbNl0sICJWZXJ0UGFyYXNpdGUiPSBjb2xvdXJfbHNbOF0gKSkgKwogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gYygiTWljcm9iZU11dHVhbGlzdCI9ICJNaWNyb2JlLVxuTXV0dWFsaXN0IiwgIk1pY3JvYmVQYXJhc2l0ZSI9ICJNaWNyb2JlLVxuUGFyYXNpdGUiLCAgIlBsYW50TXV0dWFsaXN0IiA9ICJQbGFudC1cbk11dHVhbGlzdCIsICJQbGFudFBhcmFzaXRlIj0iUGxhbnQtXG5QYXJhc2l0ZSIsICJJbnZlcnRNdXR1YWxpc3QiID0gIkludmVydGVicmF0ZS1cbk11dHVhbGlzdCIsICAgIkludmVydFBhcmFzaXRlIj0gIkludmVydGVicmF0ZS1cblBhcmFzaXRlIiwgICJWZXJ0UGFyYXNpdGUiPSAiVmVydGVicmF0ZS1cblBhcmFzaXRlIiApKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gLTEsIHkgPSByZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkbmFtZSwgbGFiZWw9IHBhc3RlKCJpdGFsaWMoayk9PSIsIHJlc19zeW1iaW9udF90YXhfc3ltYmlvc2lzMSRuKSwgcGFyc2U9VFJVRSwgaGp1c3QgPSAibGVmdCIsIHNpemU9My41KSArCiAgbGFicyh4ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMociksICIgKGNvcnJlbGF0b24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzKSIpKSApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZmlnX3N5bWJpb250X3RheF9zeW1iaW9zaXMKYGBgCgoqKlN1cHBsZW1lbnRhcnkgRmlndXJlIDQ6KioKCiMjIyBUaGUgY29tYmluZWQgZWZmZWN0IG9mIGhvc3QgYW5kIHN5bWJpb250IHRheGEKCk5PVEUgLS0gaG9zdF9zeW1iaW9udF90YXggLSAxMSB2YXJhaWJsZXMgYW5kIDU1IGNvbWJpbmF0aW9ucyEhISEKCmBgYHtyfQojIHJlb3JkZXJpbmcKZGF0JGhvc3Rfc3ltYmlvbnRfdGF4IDwtIGZhY3RvcihkYXQkaG9zdF9zeW1iaW9udF90YXgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTWljcm9iZUludmVydCIsICJNaWNyb2JlTWljcm9iZSIsICJNaWNyb2JlUGxhbnQiLCJQbGFudEludmVydCIsICJQbGFudE1pY3JvYmUiLCAiSW52ZXJ0SW52ZXJ0IiwgIkludmVydE1pY3JvYmUiLCAiSW52ZXJ0UGxhbnQiLCAiVmVydEludmVydCIsICJWZXJ0TWljcm9iZSIsICJWZXJ0VmVydCIpKQoKIyBtZXRhLXJlZ3Jlc3Npb246IG11bHRpcGxlIGludGVyY2VwdHMKbXJfaG9zdF9zeW1iaW9udF90YXgxIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBob3N0X3N5bWJpb250X3RheCAtIDEsIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0cyB4IDEwCiMgZ2V0dGluZyB0aGUgbGV2ZWwgbmFtZXMgb3V0CmxldmVsX25hbWVzIDwtIGxldmVscyhkYXQkaG9zdF9zeW1iaW9udF90YXgpCgojIGhlbHBlciBmdW5jdGlvbiB0byBydW4gbWV0YWZvciBtZXRhLXJlZ3Jlc3Npb24KcnVuX3JtYSA8LSBmdW5jdGlvbihuYW1lKSB7CiAgcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoaG9zdF9zeW1iaW9udF90YXgsIHJlZiA9IG5hbWUpLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCn0KCiMgcmVzdWx0cyBvZiBtZXRhLXJlZ3Jlc3Npb24gaW5jbHVkaW5nIGFsbCBjb250cmFzdCByZXN1bHRzOyB0YWtpbmcgdGhlIGxhc3QgbGV2ZWwgb3V0IChbLWxlbmd0aChsZXZlbF9uYW1lcyldKQptcl9ob3N0X3N5bWJpb250X3RheCA8LSBtYXAobGV2ZWxfbmFtZXNbLWxlbmd0aChsZXZlbF9uYW1lcyldLCBydW5fcm1hKQoKYGBgCgoqKlN1cHBsZW1lbnRhcnkgVGFibGUgMzoqKgpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleGFtcGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYGhvc3RfdGF4X2Jyb2FkYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfaG9zdF9zeW1iaW9udF90YXgxIDwtIFIyKG1yX2hvc3Rfc3ltYmlvbnRfdGF4MSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKcmVzX2hvc3Rfc3ltYmlvbnRfdGF4MSA8LSBnZXRfZXN0KG1yX2hvc3Rfc3ltYmlvbnRfdGF4MSwgbW9kID0gImhvc3Rfc3ltYmlvbnRfdGF4IikKcmVzX2hvc3Rfc3ltYmlvbnRfdGF4IDwtIG1hcChtcl9ob3N0X3N5bWJpb250X3RheCwgfiBnZXRfZXN0KC54LCBtb2QgPSAiaG9zdF9zeW1iaW9udF90YXgiKSkKCiMgYSBsaXN0IG9mIHRoZSBudW1iZXJzIHRvIHRha2Ugb3V0IHVubmVjZXNzYXJ5IGNvbnRyYXN0cwpjb250cmFfbGlzdCA8LSBNYXAoc2VxLCBmcm9tPTEsIHRvPTE6MTApCgojIHlvdSBuZWVkIHRvIGZsYXR0ZW4gdHdpY2U6IGZpcnN0IHRvIG1ha2UgaXQgYSBsaXN0IGFuZCBtYWtlIGl0IGEgdmVjdG9yCmVzdGlhbXRlcyA8LSBtYXAyKHJlc19ob3N0X3N5bWJpb250X3RheCwgY29udHJhX2xpc3QsIH4ueFstKC55KSwiZXN0aW1hdGUiXSkgJT4lIGZsYXR0ZW4oKSAlPiUgZmxhdHRlbl9kYmwoKQoKbG93ZXJDTHMgPC0gbWFwMihyZXNfaG9zdF9zeW1iaW9udF90YXgsIGNvbnRyYV9saXN0LCB+LnhbLSgueSksImxvd2VyQ0wiXSkgJT4lIGZsYXR0ZW4oKSAlPiUgZmxhdHRlbl9kYmwoKQoKdXBwZXJDTHMgPC0gbWFwMihyZXNfaG9zdF9zeW1iaW9udF90YXgsIGNvbnRyYV9saXN0LCB+LnhbLSgueSksInVwcGVyQ0wiXSkgJT4lIGZsYXR0ZW4oKSAlPiUgZmxhdHRlbl9kYmwoKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoYXMuY2hhcmFjdGVyKHJlc19ob3N0X3N5bWJpb250X3RheDEkbmFtZSksIGNvbnRfZ2VuKHJlc19ob3N0X3N5bWJpb250X3RheDEkbmFtZSkpLAogIEVzdGltYXRlID0gYyhyZXNfaG9zdF9zeW1iaW9udF90YXgxJGVzdGltYXRlLCBlc3RpYW10ZXMpLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMocmVzX2hvc3Rfc3ltYmlvbnRfdGF4MSRsb3dlckNMLGxvd2VyQ0xzKSwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gYyhyZXNfaG9zdF9zeW1iaW9udF90YXgxJHVwcGVyQ0wsbG93ZXJDTHMpLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfaG9zdF90YXhfc3ltYmlvc2lzMSRzaWdtYTIsICByZXAoTkEsICgxMSArIGNob29zZSgxMSwyKSktIDEpKSwKICBgUjJgID0gYyhyMl9ob3N0X3N5bWJpb250X3RheDFbMV0sIHJlcChOQSwgKDExICsgY2hvb3NlKDExLCAyKSktIDEpKSkgJT4lIGthYmxlKCJodG1sIiwgIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjMwMHB4IikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDEwfQojIGNvbG91ciBsaXN0CiNjb2xvdXJfbHMgPC0gYygiIzAwMDAwMCIsICIjRTY5RjAwIiwgIiM1NkI0RTkiLCAiIzAwOUU3MyIsICAiI0YwRTQyMiIsICAiIzAwNzJCMiIsICAiI0Q1NUUwMCIsICIjQ0M3OUE3IiwgIiMwMDAwOEIiLCAiIzhCMEE1MCIsICIjNTRGRjlGIiwgIiM5OTk5OTkiKQoKIyBhZGRpbmcgc2FtcGxlIHNpemUgKGspIGZvciBlYWNoIGNhdGVnb3J5CmtfaG9zdF9zeW1iaW9udF90YXggPC0gZGF0ICU+JSBncm91cF9ieShob3N0X3N5bWJpb250X3RheCkgJT4lIGNvdW50KCkKIyBnZXR0aW5nIGVzdGltYXRlcyBhbmQgcHJlZGljaXRvbnMKcHJlZF9ob3N0X3N5bWJpb250X3RheCA8LSBnZXRfcHJlZChtcl9ob3N0X3N5bWJpb250X3RheDEsIG1vZCA9ICJob3N0X3N5bWJpb250X3RheCIpIApyZXNfaG9zdF9zeW1iaW9udF90YXgxIDwtIGxlZnRfam9pbihyZXNfaG9zdF9zeW1iaW9udF90YXgxLCBrX2hvc3Rfc3ltYmlvbnRfdGF4LCBieSA9ICBjKCJuYW1lIiA9ICJob3N0X3N5bWJpb250X3RheCIpKSAgJT4lIGxlZnRfam9pbihwcmVkX2hvc3Rfc3ltYmlvbnRfdGF4KQojcmVzX3N5bWJpb3NpczEgCiMgZHJhd2luZyBhIGZ1bm5lbCBwbG90IC0gZmlnIDJiCmZpZ19ob3N0X3N5bWJpb250X3RheCA8LSBnZ3Bsb3QoZGF0YSA9IHJlc19ob3N0X3N5bWJpb250X3RheDEsIGFlcyh4ID0gdGFuaChlc3RpbWF0ZSksIHkgPSBuYW1lKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtMSwgMSksIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpICkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdCAlPiUgZmlsdGVyKCFpcy5uYShob3N0X3N5bWJpb250X3RheCkpLCAKICAgICAgICAgICAgICAgICAgIGFlcyh4PSB0YW5oKFpyKSwgeSA9IGhvc3Rfc3ltYmlvbnRfdGF4LCBzaXplID0gKCgxL1ZacikgKyAzKSwgY29sb3VyID0gaG9zdF9zeW1iaW9udF90YXgpLCBncm91cE9uWCA9IEZBTFNFLCBhbHBoYT0wLjQpICsgCiAgIyA5NSAlcHJlY2l0aW9uIGludGVydmFsIChQSSkKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJQUiksIHhtYXggPSB0YW5oKHVwcGVyUFIpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjYpICsKICAjIDk1ICVDSQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlckNMKSwgeG1heCA9IHRhbmgodXBwZXJDTCkpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMS4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogICMgY3JlYXRpbmcgZG90cyBhbmQgZGlmZmVyZW50IHNpemUgKGJlZS1zd2FybSBhbmQgYnViYmxlcykKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gbmFtZSksIHNpemUgPSAzLCBzaGFwZSA9IDIxKSArICMKICAjIHNldHRpbmcgY29sb3VycwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgYygiTWljcm9iZUludmVydCIgPSBjb2xvdXJfbHNbMV0sICAiTWljcm9iZU1pY3JvYmUiPSBjb2xvdXJfbHNbMl0sICJNaWNyb2JlUGxhbnQiID0gY29sb3VyX2xzWzNdLCAiUGxhbnRJbnZlcnQiID0gY29sb3VyX2xzWzRdLCJQbGFudE1pY3JvYmUiID0gY29sb3VyX2xzWzVdLCAiSW52ZXJ0SW52ZXJ0IiAgPSBjb2xvdXJfbHNbNl0sICAiSW52ZXJ0TWljcm9iZSIgPSBjb2xvdXJfbHNbN10sICJJbnZlcnRQbGFudCIgPSBjb2xvdXJfbHNbOF0sIlZlcnRJbnZlcnQiICA9IGNvbG91cl9sc1s5XSwgIlZlcnRNaWNyb2JlIj0gY29sb3VyX2xzWzEwXSwiVmVydFZlcnQiICA9IGNvbG91cl9sc1sxMV0pKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTWljcm9iZUludmVydCIgPSBjb2xvdXJfbHNbMV0sICAiTWljcm9iZU1pY3JvYmUiPSBjb2xvdXJfbHNbMl0sICJNaWNyb2JlUGxhbnQiID0gY29sb3VyX2xzWzNdLCAiUGxhbnRJbnZlcnQiID0gY29sb3VyX2xzWzRdLCJQbGFudE1pY3JvYmUiID0gY29sb3VyX2xzWzVdLCAiSW52ZXJ0SW52ZXJ0IiAgPSBjb2xvdXJfbHNbNl0sICAiSW52ZXJ0TWljcm9iZSIgPSBjb2xvdXJfbHNbN10sICJJbnZlcnRQbGFudCIgPSBjb2xvdXJfbHNbOF0sIlZlcnRJbnZlcnQiICA9IGNvbG91cl9sc1s5XSwgIlZlcnRNaWNyb2JlIj0gY29sb3VyX2xzWzEwXSwiVmVydFZlcnQiICA9IGNvbG91cl9sc1sxMV0pKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHMgPSBjKCJNaWNyb2JlSW52ZXJ0IiA9ICJNaWNyb2JlLVxuSW52ZXJ0ZWJyYXRlIiwgICJNaWNyb2JlTWljcm9iZSI9ICJNaWNyb2JlLVxuTWljcm9iZSIsICJNaWNyb2JlUGxhbnQiID0gIk1pY3JvYmUtXG5QbGFudCIsICJQbGFudEludmVydCIgPSAiUGxhbnQtXG5JbnZlcnRlYnJhdGUiLCJQbGFudE1pY3JvYmUiID0gIlBsYW50LVxuTWljcm9iZSIsICJJbnZlcnRJbnZlcnQiICA9ICJJbnZlcnRlYnJhdGVcbkludmVydGVicmF0ZSIsICAiSW52ZXJ0TWljcm9iZSIgPSAiSW52ZXJ0ZWJyYXRlLVxuTWljcm9iZSIsICJJbnZlcnRQbGFudCIgPSAiSW52ZXJ0ZWJyYXRlLVxuUGxhbnQiLCJWZXJ0SW52ZXJ0IiAgPSAiVmVydGVicmF0ZS1cbkludmVydGVicmF0ZSIsICJWZXJ0TWljcm9iZSI9ICJWZXJ0ZWJyYXRlLVxuTWljcm9iZSIsICJWZXJ0VmVydCIgID0gIlZlcnRlYnJhdGUtXG5WZXJ0ZWJyYXRlIikpICsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAtMSwgeSA9IHJlc19ob3N0X3N5bWJpb250X3RheDEkbmFtZSwgbGFiZWw9IHBhc3RlKCJpdGFsaWMoayk9PSIsIHJlc19ob3N0X3N5bWJpb250X3RheDEkbiksIHBhcnNlPVRSVUUsIGhqdXN0ID0gImxlZnQiLCBzaXplPTMuNSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKHIpLCAiIChjb3JyZWxhdG9uKSIpKSwgeSA9ICIiLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcykiKSkgKSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG91ciA9ICJub25lIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZmlnX2hvc3Rfc3ltYmlvbnRfdGF4CmBgYAoKKipTdXBwbGVtZW50YXJ5IEZpZ3VyZSA0OioqCgojIyMgQWRkdGlvbmFsIGFuYWx5c2VzCgojIyMgTW9kZWwgc2VsZWN0aW9uIChNdWxpdC1wcmVkaWN0b3IgbW9kZWwpCgpgYGB7cn0KIyBjcmVhdGVzIGEgbmV3IGZ1bmN0aW9uIHRvIHJ1biBpbiBNdU1Jbgp1cGRhdGVkLnJtYS5tdiA8LSB1cGRhdGVhYmxlKHJtYS5tdikKI3VwZGF0ZWQucm1hLm12CgojIHRlc3RpbmcgdGhlIG5ldyBmdW5jdGlvbiAKIyB1c2UgbWV0aG9kID0gIk1MIiBzbyB0aGF0IHdlIGNhbiBjb21wYXJlIEFJQwptcl9mdWxsIDwtIHVwZGF0ZWQucm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHN5bWJpb3NpcyArIAogICAgICAgICAgICAgICAgICAgICAgICAgaG9zdF90YXhfYnJvYWQgKwogICAgICAgICAgICAgICAgICAgICAgICAgc3ltYmlvbnRfdGF4X2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgIGVuZG9fb3JfZWN0byArCiAgICAgICAgICAgICAgICAgICAgICAgICBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKSwKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsCiAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kPSJNTCIsCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgc3VtbWFyeShtcl9mdWxsKQojIAojICMgdGVzdGluZyBjYWxsIG9mIG5ldyBmdW5jdGlvbgojIGdldENhbGwobXJfZnVsbCkKIyAKIyAjIHVwZGF0ZSB0aGUgbmV3IGZ1bmN0aW9uIHRvIHJ1biBpbiBNdU1JbgojIHVwZGF0ZShtcl9mdWxsKQoKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMjIyBhZGRpdGlvbmFsIG1ldGhvZHMgZm9yICJybWEubXYiIGNsYXNzIChtYWRlIGJ5IEthbWlsIEJhcnRvbikKIyMjIHdlIG5lZWQgdGhpcyB0byBydW4gbW9kZWwgc2VsZWN0aW9uIHdpdGggcm1hLm12IGluIE11TUluCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PQpmb3JtdWxhLnJtYS5tdiA8LSBmdW5jdGlvbiAoeCwgLi4uKSByZXR1cm4oZXZhbChnZXRDYWxsKHgpJG1vZHMpKQoKbWFrZUFyZ3Mucm1hLm12IDwtCiAgZnVuY3Rpb24gKG9iaiwgdGVybU5hbWVzLCBjb21iLCBvcHQsIC4uLikgewogICAgcmV0IDwtIE11TUluOjo6bWFrZUFyZ3MuZGVmYXVsdChvYmosIHRlcm1OYW1lcywgY29tYiwgb3B0KQogICAgbmFtZXMocmV0KVsxTF0gPC0gIm1vZHMiCiAgICByZXQKICB9Cgpub2JzLnJtYS5tdiA8LQogIGZ1bmN0aW9uIChvYmplY3QsIC4uLikKICAgIGF0dHIobG9nTGlrKG9iamVjdCksICJuYWxsIikKCmNvZWZUYWJsZS5ybWEubXYgPC0gZnVuY3Rpb24gKG1vZGVsLCAuLi4pCiAgTXVNSW46OjoubWFrZUNvZWZUYWJsZShtb2RlbCRiLCBtb2RlbCRzZSwgY29lZk5hbWVzID0gcm93bmFtZXMobW9kZWwkYikpCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKIyB0ZXN0aW5nIGRyZWRnZQojZHJlZGdlKGZ1bGwubW9kZWwsIGV2YWx1YXRlPUYpICMgc2hvdyBhbGwgY2FuZGlkYXRlIG1vZGVscwojIG4gPSAzMiBtb2RlbCBleGlzaXQKY2FuZGlkYXRlcyA8LSBkcmVkZ2UobXJfZnVsbCkKCiMgZGlzcGxheXMgZGVsdGEgQUlDYyA8MgpjYW5kaWRhdGVzX2FpYzIgPC0gc3Vic2V0KGNhbmRpZGF0ZXMsIGRlbHRhIDwgMikKCiMgbW9kZWwgYXZlcmFnaW5nCiMgaXQgc2VlbXMgbGlrZSBtb2RlbHMgYXJlIHVzaW5nIHogdmFsdWVzIHJhdGhlciB0aGFuIHQgdmFsdWVzICh3aGljaCB3aWxsIGJlIE9LKQptcl9hdmVyYWdlZF9haWMyIDwtIHN1bW1hcnkobW9kZWwuYXZnKGNhbmRpZGF0ZXMsICBkZWx0YSA8IDIpKQoKIyByZWxhdGl2ZSBpbXBvcnRhbmNlIG9mIGVhY2ggcHJlZGljdG9yCmltcG9ydGFuY2UgPC0gaW1wb3J0YW5jZShjYW5kaWRhdGVzKQoKIyB1c2UgUkVNTCBpZiBub3QgZm9yIG1vZGVsIGNvbXBhcmlzaW9uCm1vZGVsMSA8LSBybWEubXYoeWkgPSBaciwgViA9IFZaciwgbW9kcyA9IH4gIG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkICsgaG9zdF90YXhfYnJvYWQsIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgbWV0aG9kPSJSRU1MIiwgZGF0YSA9IGRhdCkKbW9kZWwyIDwtIHJtYS5tdih5aSA9IFpyLCBWID0gVlpyLCBtb2RzID0gfiAgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgKyBob3N0X3RheF9icm9hZCArIHN5bWJpb3NpcywgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCBtZXRob2Q9IlJFTUwiLCBkYXRhID0gZGF0KQoKYGBgCgoqKiB0YWJsZSBtb2RlbCBhaWMgZXRjCmBgYHtyfQojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBNb2RlbCAodmFyaWFibGUgd2VpZ2h0KWAgPSBjKCJNb2RlbDEiLCAiTW9kZWwyIiwgIihTdW0gb2Ygd2VpZ2h0cykiKSwKICB0cmFuc21pc3Npb24gPSBjKGlmX2Vsc2UoY2FuZGlkYXRlc19haWMyJG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkID09ICIrIiwgIiQrJCIsICJOQSIpLHJvdW5kKGltcG9ydGFuY2VbMV0sMykgKSwKICBob3N0X3RheCA9IGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkaG9zdF90YXhfYnJvYWQ9PSAiKyIsICIkKyQiLCAiTkEiKSxyb3VuZChpbXBvcnRhbmNlWzJdLCAzKSksCiAgc3ltYmlvc2lzID0gIGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkc3ltYmlvc2lzPT0gIisiLCAiJCskIiwgIk5BIikscm91bmQoaW1wb3J0YW5jZVszXSwgMykpLAogIHN5bWJpb250X3RheCA9IGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkc3ltYmlvbnRfdGF4X2Jyb2FkPT0gIisiLCAiJCskIiwgIk5BIikscm91bmQoaW1wb3J0YW5jZVs0XSwgMykpLAogIGVuZG9fb3JfZWN0byA9IGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkZW5kb19vcl9lY3RvPT0gIisiLCAiJCskIiwgIk5BIikscm91bmQoaW1wb3J0YW5jZVs1XSwgMykpLAogIGBob3N0X3JhbmdlYCA9IGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkYGxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pYD09ICIrIiwgIiQrJCIsICJOQSIpLHJvdW5kKGltcG9ydGFuY2VbNl0sIDMpKSwKICBkZWx0YV9BSUNjID0gYyhjYW5kaWRhdGVzX2FpYzIkZGVsdGEsIE5BKSwKICBXZWlnaHQgPSBjKGNhbmRpZGF0ZXNfYWljMiR3ZWlnaHQsIE5BKSkgJT4lIAogIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKQpgYGAKCioqIG1vZGVsIGF2ZXJhZ2VkIGVzdGlhbXRlcyAoZnVsbCBhdmVyYWdlKQpgYGB7cn0KCiMgZ2V0dGluZyBhdmVyYWdlZCBSMiBhbmQgdmFyaWFuY2UgY29tcG9uZW50cyBub3QgcHJvdmlkZWQgYnkgdGhlIE11TUluIHBhY2thZ2UKYXZlcmFnZV9zaWdtYTIgPC0gd2VpZ2h0ZWQubWVhbih4ID0gYyhtb2RlbDEkc2lnbWEyLCBtb2RlbDIkc2lnbWEyKSwgdyA9IGNhbmRpZGF0ZXNfYWljMiR3ZWlnaHQpCmF2ZXJhZ2VfUjIgPC0gd2VpZ2h0ZWQubWVhbih4ID0gYyhSMihtb2RlbDEpWzFdLCBSMihtb2RlbDIpWzFdKSAgLHcgPSBjYW5kaWRhdGVzX2FpYzIkd2VpZ2h0KQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoIkludGVyY2VwdCAoYm90aC1NaWNyb2JlLU11dHVsaXN0KSIsCiAgICAgICAgICAgICAgICAgICAgICJNaWNyb2JlLVBsYW50IiwgIk1pY3JvYmUtSW52ZXJ0IiwgIk1pY3JvYmUtVmVydCIsIAogICAgICAgICAgICAgICAgICAgICAiYm90aC1ob3Jpem9udGFsIiwgImJvdGgtdmVydGljYWwiLCAiTXV0dWxpc3QtUGFyYXNpdGUiKSwKICBFc3RpbWF0ZSA9IG1yX2F2ZXJhZ2VkX2FpYzIkY29lZm1hdC5mdWxsWywxXSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSAgbXJfYXZlcmFnZWRfYWljMiRjb2VmbWF0LmZ1bGxbLDFdIC0gbXJfYXZlcmFnZWRfYWljMiRjb2VmbWF0LmZ1bGxbLDJdKnFub3JtKDAuOTc1KSwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gIG1yX2F2ZXJhZ2VkX2FpYzIkY29lZm1hdC5mdWxsWywxXSArIG1yX2F2ZXJhZ2VkX2FpYzIkY29lZm1hdC5mdWxsWywyXSpxbm9ybSgwLjk3NSksCiAgYFZbYXV0aG9yc11gID0gYyhhdmVyYWdlX3NpZ21hMiwgcmVwKE5BLDYpKSwKICBgUjJgID0gYyhhdmVyYWdlX1IyLCByZXAoTkEsNikpKSAlPiUgCiAga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAoKIyMgUHVibGljYXRpb24gQmlhcyBhbmQgU2Vuc2l0aXZpdHkgQW5hbHlzaXMKCiogYm91bmRhcnkgcHJvYmxlbXMKICoqIG5vIG9mIHJhbmRvbXphdGlvbnMgYW5kIGxpbWl0X3JlYXJjaGVkCiogVGltZSBsYWcgYmlhcwoKIyMjIFJlc2lkdWFsIGZ1bm5lbCBwbG90IDEKCmBgYHtyfQojIApyZXNfZnVubmVsX3Bsb3QgPC0gcm1hLm12KHlpID0gWnIsIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3N0X3RheF9icm9hZCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN5bWJpb3NpcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCBkYXRhID0gZGF0KQoKZnVubmVsKHJlc19mdW5uZWxfcGxvdCwgeWF4aXMgPSAic2VpbnYiKQpgYGAKCioqU3VwcGxlbWVudGFyeSBGaWd1cmUgNToqKgoKIyMjIFVuaXZhcmFpdGUgRWdnZXIgcmVncmVzc2lvbgoKYGBge3J9CiMgCmVnZ2VyX3JlZ3Jlc3Npb25fdW5pIDwtIHJtYS5tdih5aSA9IFpyLCBWID0gVlpyLCBtb2RzID0gfiBzcXJ0KFZaciksIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIGRhdGEgPSBkYXQpCgpgYGAKCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgc3ltYmlvbnRfdGF4X2Jyb2FkYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfZWdnZXJfcmVncmVzc2lvbl91bmkgPC0gUjIoZWdnZXJfcmVncmVzc2lvbl91bmkpCgojIGdldHRpbmcgZXN0aW1hdGVzOiBuYW1lIGRvZXMgbm90IHdvcmsgZm9yIHNsb3BlcwpyZXNfZWdnZXJfcmVncmVzc2lvbl91bmkgPC0gZ2V0X2VzdChlZ2dlcl9yZWdyZXNzaW9uX3VuaSwgbW9kID0gInNxcnQoVlpyKSIpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYygiSW50ZXJjZXB0IiwgInNxcnQoVlpyKSIpLAogIEVzdGltYXRlID0gYyhyZXNfZWdnZXJfcmVncmVzc2lvbl91bmkkZXN0aW1hdGUpLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMocmVzX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pJGxvd2VyQ0wpLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19lZ2dlcl9yZWdyZXNzaW9uX3VuaSR1cHBlckNMKSwKICBgVlthdXRob3JzXWAgPSBjKGVnZ2VyX3JlZ3Jlc3Npb25fdW5pJHNpZ21hMiwgTkEpLAogIGBSMmAgPSBjKHIyX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pWzFdLCBOQSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDR9CnByZWRfZWdnZXJfcmVncmVzc2lvbl91bmkgPC1wcmVkaWN0LnJtYShlZ2dlcl9yZWdyZXNzaW9uX3VuaSkgCgojIHBsb3R0aW5nCgpmaXRfZWdnZXJfcmVncmVzc2lvbl91bmkgPC0gIGRhdCAlPiUgCiAgbXV0YXRlKHltaW4gPSBwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pJGNpLmxiLCAKICAgICAgICAgeW1heCA9IHByZWRfZWdnZXJfcmVncmVzc2lvbl91bmkkY2kudWIsCiAgICAgICAgIHltaW4yID0gcHJlZF9lZ2dlcl9yZWdyZXNzaW9uX3VuaSRjci5sYiwKICAgICAgICAgeW1heDIgPSBwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pJGNyLnViLAogICAgICAgICBwcmVkID0gcHJlZF9lZ2dlcl9yZWdyZXNzaW9uX3VuaSRwcmVkKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3FydChWWnIpLCB5ID0gWnIsIHNpemUgPSAoMS9WWnIpICsgMykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGZpbGwgPSAiZ3JleTkwIikgKwogICNnZW9tX3JpYmJvbihhZXMoeW1pbiA9IHltaW4sIHltYXggPSB5bWF4KSwgZmlsbCA9ICIjMDA3MkIyIikgICsgIyBub3QgcXVpdGUgc3VyZSB3aHkgdGhpcyBkb2VzIG5vdCB3b3JrCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluMiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAgImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9ICIjMDA3MkIyIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1heDIpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9ICIjMDA3MkIyIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1pbiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLGx0eSA9ICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSIjRDU1RTAwIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1heCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSIjRDU1RTAwIikgKyAKICBnZW9tX3Ntb290aChhZXMoeSA9IHByZWQpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0iZGFzaGVkIiwgbHdkID0gMC41LCBjb2xvdXIgPSJibGFjayIpICsgIAogIHlsaW0oLTEsIDIpICsgeGxpbSgwLjA1LCAwLjQ1KSArCiAgI2dlb21fYWJsaW5lKGludGVyY2VwdCA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1sxXV0sIHNsb3BlID0gbXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvJGJldGFbWzJdXSwgYWxwaGEgPSAwLjcsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAwLjUpICsKICBsYWJzKHggPSAic3FydChzYW1wbGluZyB2YXJpYW5jZSkiLCB5ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMoWnIpLCAiIChlZmZlY3Qgc2l6ZSkiKSksIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzKSIpKSkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICAjIHRoZW1zZXMKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgCgpmaXRfZWdnZXJfcmVncmVzc2lvbl91bmkKYGBgCgojIyMgTXVsdGl2YXJhaXRlIEVnZ2VyIHJlZ3Jlc3Npb24KCmBgYHtyfQojIAplZ2dlcl9yZWdyZXNzaW9uX211bCA8LSBybWEubXYoeWkgPSBaciwgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBzcXJ0KFZacikgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvc3RfdGF4X2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ltYmlvc2lzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIGRhdGEgPSBkYXQpCgpgYGAKCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgc3ltYmlvbnRfdGF4X2Jyb2FkYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfZWdnZXJfcmVncmVzc2lvbl9tdWwgPC0gUjIoZWdnZXJfcmVncmVzc2lvbl9tdWwpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYygiSW50ZXJjZXB0IChib3RoLU1pY3JvYmUtTXV0dWxpc3QpIiwgInNxcnQoVlpyKSIsICJib3RoLWhvcml6b250YWwiLCAiYm90aC12ZXJ0aWNhbCIsIAogICAgICAgICAgICAgICAgICAgICAiTWljcm9iZS1QbGFudCIsICJNaWNyb2JlLUludmVydCIsICJNaWNyb2JlLVZlcnQiLCAiTXV0dWxpc3QtUGFyYXNpdGUiKSwKICBFc3RpbWF0ZSA9IGMoZWdnZXJfcmVncmVzc2lvbl9tdWwkYiksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhlZ2dlcl9yZWdyZXNzaW9uX211bCRjaS5sYiksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMoZWdnZXJfcmVncmVzc2lvbl9tdWwkY2kudWIpLAogIGBWW2F1dGhvcnNdYCA9IGMoZWdnZXJfcmVncmVzc2lvbl9tdWwkc2lnbWEyLCByZXAoTkEsNykpLAogIGBSMmAgPSBjKHIyX2VnZ2VyX3JlZ3Jlc3Npb25fbXVsWzFdLCByZXAoTkEsNykpKSAlPiUga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAoKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSA0fQpwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fbXVsIDwtcHJlZGljdC5ybWEoZWdnZXJfcmVncmVzc2lvbl9tdWwpIAoKIyBwbG90dGluZwoKZml0X2VnZ2VyX3JlZ3Jlc3Npb25fbXVsIDwtICBkYXQgJT4lIAogIGZpbHRlcighaXMubmEobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQpICYgIWlzLm5hKGhvc3RfdGF4X2Jyb2FkKSAmICFpcy5uYShzeW1iaW9zaXMpKSAgJT4lICMgZ2V0dGluZyByaWRlIG9mIE5BIHZhbHVlcwogIG11dGF0ZSh5bWluID0gcHJlZF9lZ2dlcl9yZWdyZXNzaW9uX211bCRjaS5sYiwgCiAgICAgICAgIHltYXggPSBwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fbXVsJGNpLnViLAogICAgICAgICB5bWluMiA9IHByZWRfZWdnZXJfcmVncmVzc2lvbl9tdWwkY3IubGIsCiAgICAgICAgIHltYXgyID0gcHJlZF9lZ2dlcl9yZWdyZXNzaW9uX211bCRjci51YiwKICAgICAgICAgcHJlZCA9IHByZWRfZWdnZXJfcmVncmVzc2lvbl9tdWwkcHJlZCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHNxcnQoVlpyKSwgeSA9IFpyLCBzaXplID0gKDEvVlpyKSArIDMpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBmaWxsID0gImdyZXk5MCIpICsKICAjZ2VvbV9yaWJib24oYWVzKHltaW4gPSB5bWluLCB5bWF4ID0geW1heCksIGZpbGwgPSAiIzAwNzJCMiIpICArICMgbm90IHF1aXRlIHN1cmUgd2h5IHRoaXMgZG9lcyBub3Qgd29yawogIGdlb21fc21vb3RoKGFlcyh5ID0geW1pbjIpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0gICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSAiIzAwNzJCMiIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltYXgyKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSAiIzAwNzJCMiIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltaW4pLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSxsdHkgPSAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0iI0Q1NUUwMCIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltYXgpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0iZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0iI0Q1NUUwMCIpICsgCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSBwcmVkKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ImRhc2hlZCIsIGx3ZCA9IDAuNSwgY29sb3VyID0iYmxhY2siKSArICAKICB5bGltKC0xLCAyKSArIHhsaW0oMC4wNSwgMC40NSkgKwogICNnZW9tX2FibGluZShpbnRlcmNlcHQgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMV1dLCBzbG9wZSA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1syXV0sIGFscGhhID0gMC43LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMC41KSArCiAgbGFicyh4ID0gInNxcnQoc2FtcGxpbmcgdmFyaWFuY2UpIiwgeSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKFpyKSwgIiAoZWZmZWN0IHNpemUpIikpLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcykiKSkpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgIyB0aGVtc2VzCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZml0X2VnZ2VyX3JlZ3Jlc3Npb25fbXVsCmBgYAoKKipTdXBwbGVtZW50YXJ5IEZpZ3VyZSA1OioqCgppdCBpcyBub3QgbGluZWFyIGJlY3Vhc2UgdGhlc2UgYXJlIAoKIyMjIFJlc2lkdWFsIGZ1bm5lbCBwbG90IDIKCmBgYHtyfQojIApyZXNfZnVubmVsX3Bsb3QyIDwtIHJtYS5tdih5aSA9IFpyLCBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHNxcnQoVlpyKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3N0X3RheF9icm9hZCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN5bWJpb3NpcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCBkYXRhID0gZGF0KQoKZnVubmVsKHJlc19mdW5uZWxfcGxvdDIsIHlheGlzID0gInNlaW52IikKYGBgCgoqKlN1cHBsZW1lbnRhcnkgRmlndXJlIDY6KioKCiMjIyBVbml2YXJhaXRlIHRpbWUtbGFnIGJpYXMKYGBge3J9CiMgCnRpbWVfbGFnX2VmZmVjdF91bmkgPC0gcm1hLm12KHlpID0gWnIsIFYgPSBWWnIsIG1vZHMgPSB+IHllYXIsIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIGRhdGEgPSBkYXQpCgpgYGAKCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgc3ltYmlvbnRfdGF4X2Jyb2FkYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfdGltZV9sYWdfZWZmZWN0X3VuaSA8LSBSMih0aW1lX2xhZ19lZmZlY3RfdW5pKQoKIyBnZXR0aW5nIGVzdGltYXRlczogbmFtZSBkb2VzIG5vdCB3b3JrIGZvciBzbG9wZXMKcmVzX3RpbWVfbGFnX2VmZmVjdF91bmkgPC0gZ2V0X2VzdCh0aW1lX2xhZ19lZmZlY3RfdW5pLCBtb2QgPSAieWVhciIpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYygiSW50ZXJjZXB0IiwgIlllYXIiKSwKICBFc3RpbWF0ZSA9IGMocmVzX3RpbWVfbGFnX2VmZmVjdF91bmkkZXN0aW1hdGUpLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMocmVzX3RpbWVfbGFnX2VmZmVjdF91bmkkbG93ZXJDTCksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX3RpbWVfbGFnX2VmZmVjdF91bmkkdXBwZXJDTCksCiAgYFZbYXV0aG9yc11gID0gYyh0aW1lX2xhZ19lZmZlY3RfdW5pJHNpZ21hMiwgTkEpLAogIGBSMmAgPSBjKHIyX3RpbWVfbGFnX2VmZmVjdF91bmlbMV0sIE5BKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKQpgYGAKCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0gNH0KcHJlZF90aW1lX2xhZ19lZmZlY3RfdW5pIDwtcHJlZGljdC5ybWEodGltZV9sYWdfZWZmZWN0X3VuaSkgCgojIHBsb3R0aW5nCgpmaXRfdGltZV9sYWdfZWZmZWN0IDwtICBkYXQgJT4lIAogIG11dGF0ZSh5bWluID0gcHJlZF90aW1lX2xhZ19lZmZlY3RfdW5pJGNpLmxiLCAKICAgICAgICAgeW1heCA9IHByZWRfdGltZV9sYWdfZWZmZWN0X3VuaSRjaS51YiwKICAgICAgICAgeW1pbjIgPSBwcmVkX3RpbWVfbGFnX2VmZmVjdF91bmkkY3IubGIsCiAgICAgICAgIHltYXgyID0gcHJlZF90aW1lX2xhZ19lZmZlY3RfdW5pJGNyLnViLAogICAgICAgICBwcmVkID0gcHJlZF90aW1lX2xhZ19lZmZlY3RfdW5pJHByZWQpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gWnIsIHNpemUgPSAoMS9WWnIpICsgMykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGZpbGwgPSAiZ3JleTkwIikgKwogICNnZW9tX3JpYmJvbihhZXMoeW1pbiA9IHltaW4sIHltYXggPSB5bWF4KSwgZmlsbCA9ICIjMDA3MkIyIikgICsgIyBub3QgcXVpdGUgc3VyZSB3aHkgdGhpcyBkb2VzIG5vdCB3b3JrCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluMiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAgImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9ICIjMDA3MkIyIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1heDIpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9ICIjMDA3MkIyIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1pbiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLGx0eSA9ICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSIjRDU1RTAwIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1heCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSIjRDU1RTAwIikgKyAKICBnZW9tX3Ntb290aChhZXMoeSA9IHByZWQpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0iZGFzaGVkIiwgbHdkID0gMC41LCBjb2xvdXIgPSJibGFjayIpICsgIAogIHlsaW0oLTEsIDIpICsgeGxpbSgxOTk0LDIwMTkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygxOTk1LCAyMDAwLCAyMDA1LCAyMDEwLCAyMDE1LCAyMDIwKSkgKyAKICAjZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gbXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvJGJldGFbWzFdXSwgc2xvcGUgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMl1dLCBhbHBoYSA9IDAuNywgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDAuNSkgKwogIGxhYnMoeCA9ICJZZWFyIiwgeSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKFpyKSwgIiAoZWZmZWN0IHNpemUpIikpLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcykiKSkpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgIyB0aGVtc2VzCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZml0X3RpbWVfbGFnX2VmZmVjdApgYGAKCioqU3VwcGxlbWVudGFyeSBGaWd1cmUgNjoqKgoKIyMjIE11bHRpdmFyYWl0ZSB0aW1lLWxhZyBiaWFzCmBgYHtyfQojIAp0aW1lX2xhZ19lZmZlY3RfbXVsIDwtIHJtYS5tdih5aSA9IFpyLCBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4geWVhciArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvc3RfdGF4X2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeW1iaW9zaXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIGRhdGEgPSBkYXQpCgpgYGAKCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgc3ltYmlvbnRfdGF4X2Jyb2FkYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfdGltZV9sYWdfZWZmZWN0X211bCA8LSBSMih0aW1lX2xhZ19lZmZlY3RfbXVsKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoIkludGVyY2VwdCAoYm90aC1NaWNyb2JlLU11dHVsaXN0KSIsICJZZWFyIiwgImJvdGgtaG9yaXpvbnRhbCIsICJib3RoLXZlcnRpY2FsIiwgCiAgICAgICAgICAgICAgICAgICAgICJNaWNyb2JlLVBsYW50IiwgIk1pY3JvYmUtSW52ZXJ0IiwgIk1pY3JvYmUtVmVydCIsICJNdXR1bGlzdC1QYXJhc2l0ZSIpLAogIEVzdGltYXRlID0gYyh0aW1lX2xhZ19lZmZlY3RfbXVsJGIpLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGModGltZV9sYWdfZWZmZWN0X211bCRjaS5sYiksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGModGltZV9sYWdfZWZmZWN0X211bCRjaS51YiksCiAgYFZbYXV0aG9yc11gID0gYyh0aW1lX2xhZ19lZmZlY3RfbXVsJHNpZ21hMiwgcmVwKE5BLDcpKSwKICBgUjJgID0gYyhyMl90aW1lX2xhZ19lZmZlY3RfbXVsWzFdLCByZXAoTkEsNykpKSAlPiUga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAoKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSA0fQpwcmVkX3RpbWVfbGFnX2VmZmVjdF9tdWwgPC1wcmVkaWN0LnJtYSh0aW1lX2xhZ19lZmZlY3RfbXVsKSAKCiMgcGxvdHRpbmcKZml0X3RpbWVfbGFnX2VmZmVjdF9tdWwgPC0gIGRhdCAlPiUgCiAgZmlsdGVyKCFpcy5uYShtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCkgJiAhaXMubmEoaG9zdF90YXhfYnJvYWQpICYgIWlzLm5hKHN5bWJpb3NpcykpICAlPiUgCiAgbXV0YXRlKHltaW4gPSBwcmVkX3RpbWVfbGFnX2VmZmVjdF9tdWwkY2kubGIsIAogICAgICAgICB5bWF4ID0gcHJlZF90aW1lX2xhZ19lZmZlY3RfbXVsJGNpLnViLAogICAgICAgICB5bWluMiA9IHByZWRfdGltZV9sYWdfZWZmZWN0X211bCRjci5sYiwKICAgICAgICAgeW1heDIgPSBwcmVkX3RpbWVfbGFnX2VmZmVjdF9tdWwkY3IudWIsCiAgICAgICAgIHByZWQgPSBwcmVkX3RpbWVfbGFnX2VmZmVjdF9tdWwkcHJlZCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBaciwgc2l6ZSA9ICgxL1ZacikgKyAzKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZmlsbCA9ICJncmV5OTAiKSArCiAgI2dlb21fcmliYm9uKGFlcyh5bWluID0geW1pbiwgeW1heCA9IHltYXgpLCBmaWxsID0gIiMwMDcyQjIiKSAgKyAjIG5vdCBxdWl0ZSBzdXJlIHdoeSB0aGlzIGRvZXMgbm90IHdvcmsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltaW4yKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ICAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4MiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4KSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArIAogIGdlb21fc21vb3RoKGFlcyh5ID0gcHJlZCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkYXNoZWQiLCBsd2QgPSAwLjUsIGNvbG91ciA9ImJsYWNrIikgKyAgCiAgeWxpbSgtMSwgMikgKyB4bGltKDE5OTQsMjAxOSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDE5OTUsIDIwMDAsIDIwMDUsIDIwMTAsIDIwMTUsIDIwMjApKSArIAogICNnZW9tX2FibGluZShpbnRlcmNlcHQgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMV1dLCBzbG9wZSA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1syXV0sIGFscGhhID0gMC43LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMC41KSArCiAgbGFicyh4ID0gIlllYXIiLCB5ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMoWnIpLCAiIChlZmZlY3Qgc2l6ZSkiKSksIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzKSIpKSkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICAjIHRoZW1zZXMKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgCgpmaXRfdGltZV9sYWdfZWZmZWN0X211bApgYGAKCioqU3VwcGxlbWVudGFyeSBGaWd1cmUgNjoqKiAtIG5vdCBsaW5lYXIKCiMjIyBTZW5zaXRpdml0eSB0ZXN0IDE6IHRoZSBudW1iZXIgb2YgcmFuZGFtaXphdGlvbnMKCiogYm91bmRhcnkgcHJvYmxlbXMKICoqIG5vIG9mIHJhbmRvbXphdGlvbnMgYW5kIGxpbWl0X3JlYXJjaGVkID0gaWYgdGhleSBhcmUgZGlmZmVyZW50LCB0aGVuLCBpdCBjb3VsZCBsZWFkIHRvIGJpYXMKICoqIGxpbWl0X3JlYWNoZWQgPSBpZiBoaWdoIC0gbW9yZSBsaWtsZXkgdG8gYmUgdW5kZXJlc3RpYW10ZWQgCiAKIyMjIFRoZSB0eXBlIG9mIHN5bWJpb3NpczogcGFyYXNpdGlzbSB2cy4gbXV0dWFsaXNtCgpgYGB7cn0KIyAyMzMgLS0tIFllcyA9IDc0ICgwLjMxNzU5NjYlKTsgTm8gPSAxNTkKCiMgc3ltYmlvc2lzCiMgbXVsdGlwbGUgaW50ZXJjZXB0cwpzYV9yYW5kb21fc3ltYmlvc2lzMTwtbG1lcihsb2cobm9fcmFuZG9taXphdGlvbnMpIH4gc3ltYmlvc2lzIC0gMSArICgxIHwgYXV0aG9ycyksIGRhdGEgPSBkYXQpCiNjb250cmFzdApzYV9yYW5kb21fc3ltYmlvc2lzMjwtbG1lcihsb2cobm9fcmFuZG9taXphdGlvbnMpIH4gc3ltYmlvc2lzICsgKDEgfCBhdXRob3JzKSwgZGF0YSA9IGRhdCkKCmBgYAoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDM6KioKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhhbXBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBzeW1iaW9udF90YXhfYnJvYWRgLiAKCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfc2FfcmFuZG9tX3N5bWJpb3NpcyA8LSByMl9uYWthZ2F3YShzYV9yYW5kb21fc3ltYmlvc2lzMSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKCnJlc19zYV9yYW5kb21fc3ltYmlvc2lzPC0gdGliYmxlKGVzdGlhbXRlID0gYyhmaXhlZihzYV9yYW5kb21fc3ltYmlvc2lzMSksIGZpeGVmKHNhX3JhbmRvbV9zeW1iaW9zaXMyKVsyXSkpCgpjaV9zYV9yYW5kb21fc3ltYmlvc2lzMTwtY29uZmludChzYV9yYW5kb21fc3ltYmlvc2lzMSkKY2lfc2FfcmFuZG9tX3N5bWJpb3NpczI8LWNvbmZpbnQoc2FfcmFuZG9tX3N5bWJpb3NpczIpCnJlc19zYV9yYW5kb21fc3ltYmlvc2lzICU8PiUgbXV0YXRlKGxvd2VyQ0wgPSBjKGNpX3NhX3JhbmRvbV9zeW1iaW9zaXMxWzM6NCwxXSwgY2lfc2FfcmFuZG9tX3N5bWJpb3NpczJbNCwxXSkpCnJlc19zYV9yYW5kb21fc3ltYmlvc2lzICU8PiUgbXV0YXRlKHVwcGVyQ0wgPSBjKGNpX3NhX3JhbmRvbV9zeW1iaW9zaXMxWzM6NCwyXSwgY2lfc2FfcmFuZG9tX3N5bWJpb3NpczJbNCwyXSkpCiAgICAgICAgICAgCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKGFzLmNoYXJhY3RlcihyZXNfc3ltYmlvc2lzMSRuYW1lKSwgY29udF9nZW4ocmVzX3N5bWJpb3NpczEkbmFtZSkpLAogIEVzdGltYXRlID0gcmVzX3NhX3JhbmRvbV9zeW1iaW9zaXMkZXN0aWFtdGUsCiAgYExvd2VyIENJIFswLjAyNV1gID0gcmVzX3NhX3JhbmRvbV9zeW1iaW9zaXMkbG93ZXJDTCwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gcmVzX3NhX3JhbmRvbV9zeW1iaW9zaXMkdXBwZXJDTCwKICBgVlthdXRob3JzXWAgPSBjKGF0dHIoVmFyQ29ycihzYV9yYW5kb21fc3ltYmlvc2lzMSkkYXV0aG9yLCJzdGRkZXYiKV4yLCAgcmVwKE5BLCAyKSksCiAgYFZbcmVzaWR1YWxzXWAgPWMoYXR0cihWYXJDb3JyKHNhX3JhbmRvbV9zeW1iaW9zaXMxKSwic2MiKV4yLCByZXAoTkEsIDIpKSwKICBgUjJgID0gYyhyMl9zYV9yYW5kb21fc3ltYmlvc2lzJFIyX21hcmdpbmFsLCByZXAoTkEsIDIpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKYGBgCgojIyMgVGhlIGVmZmVjdCBvZiBob3N0IHRheGEKCmBgYHtyfQojIGhvc3RfdGF4X2Jyb2FkCiMgbXV0aXBsZSBpbnRlcmNlcHRzCnNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDE8LWxtZXIobG9nKG5vX3JhbmRvbWl6YXRpb25zKSB+IGhvc3RfdGF4X2Jyb2FkIC0gMSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxIHwgYXV0aG9ycyksIGRhdGEgPSBkYXQpCiMgY29udHJhc3QgMQpzYV9yYW5kb21faG9zdF90YXhfYnJvYWQyPC1sbWVyKGxvZyhub19yYW5kb21pemF0aW9ucykgfiBob3N0X3RheF9icm9hZCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8IGF1dGhvcnMpLCBkYXRhID0gZGF0KQojIGNvbnRyYXN0IDIKc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMzwtbG1lcihsb2cobm9fcmFuZG9taXphdGlvbnMpIH4gcmVsZXZlbChob3N0X3RheF9icm9hZCwgcmVmID0gIlBsYW50IikgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEgfCBhdXRob3JzKSwgZGF0YSA9IGRhdCkKCiMgY29udHJhc3QgMwpzYV9yYW5kb21faG9zdF90YXhfYnJvYWQ0PC1sbWVyKGxvZyhub19yYW5kb21pemF0aW9ucykgfiByZWxldmVsKGhvc3RfdGF4X2Jyb2FkLCByZWYgPSAiSW52ZXJ0IikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxIHwgYXV0aG9ycyksIGRhdGEgPSBkYXQpCmBgYAoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDM6KioKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhhbXBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBzeW1iaW9udF90YXhfYnJvYWRgLiAKCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkIDwtIHIyX25ha2FnYXdhKHNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDEpCgojIGdldHRpbmcgZXN0aW1hdGVzCnJlc19zYV9yYW5kb21faG9zdF90YXhfYnJvYWQgPC0gdGliYmxlKGVzdGlhbXRlID0gYyhmaXhlZihzYV9yYW5kb21faG9zdF90YXhfYnJvYWQxKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhlZihzYV9yYW5kb21faG9zdF90YXhfYnJvYWQyKVsyOjRdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4ZWYoc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMylbMzo0XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVmKHNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDQpWzRdKSkgCiAgCmNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDE8LWNvbmZpbnQoc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMSkKY2lfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMjwtY29uZmludChzYV9yYW5kb21faG9zdF90YXhfYnJvYWQyKQpjaV9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQzPC1jb25maW50KHNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDMpCmNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDQ8LWNvbmZpbnQoc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkNCkKcmVzX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZCAlPD4lIG11dGF0ZShsb3dlckNMID0gYyhjaV9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQxWzM6NiwxXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDJbNDo2LDFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaV9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQzWzU6NiwxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkNFs2LDFdKSkKcmVzX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZCAlPD4lIG11dGF0ZSh1cHBlckNMID0gYyhjaV9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQxWzM6NiwyXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDJbNDo2LDJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaV9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQzWzU6NiwyXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkNFs2LDJdKSkKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9ICBjKGFzLmNoYXJhY3RlcihyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSRuYW1lKSwgY29udF9nZW4ocmVzX3N5bWJpb250X3RheF9icm9hZDEkbmFtZSkpLCAjIGRvbmUKICBFc3RpbWF0ZSA9IHJlc19zYV9yYW5kb21faG9zdF90YXhfYnJvYWQkZXN0aWFtdGUsCiAgYExvd2VyIENJIFswLjAyNV1gID0gcmVzX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZCRsb3dlckNMLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSByZXNfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkJHVwcGVyQ0wsCiAgYFZbYXV0aG9yc11gID0gYyhhdHRyKFZhckNvcnIoc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMSkkYXV0aG9yLCJzdGRkZXYiKV4yLCAgcmVwKE5BLCA5KSksCiAgYFZbcmVzaWR1YWxzXWAgPWMoYXR0cihWYXJDb3JyKHNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDEpLCJzYyIpXjIsIHJlcChOQSwgOSkpLAogIGBSMmAgPSBjKHIyX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZCRSMl9tYXJnaW5hbCwgcmVwKE5BLCA5KSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgCmBgYAoKCiMjIyBUaGUgZWZmZWN0IG9mIHRoZSBtb2RlbCBvZiB0cmFuc21pc3Npb24KCmBgYHtyfQojIG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkCgpzYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxPC1sbWVyKGxvZyhub19yYW5kb21pemF0aW9ucykgfiBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCAtIDEgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxIHwgYXV0aG9ycyksIGRhdGEgPSBkYXQpCgoKIyBjb250cmFzdCAxCnNhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDI8LWxtZXIobG9nKG5vX3JhbmRvbWl6YXRpb25zKSB+IG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxIHwgYXV0aG9ycyksIGRhdGEgPSBkYXQpCgojIGNvbnRyYXN0IDIKc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMyA8LSBsbWVyKGxvZyhub19yYW5kb21pemF0aW9ucykgfiByZWxldmVsKG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkLCByZWYgPSAidmVydGljYWwiKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8IGF1dGhvcnMpLCBkYXRhID0gZGF0KQpgYGAKCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgc3ltYmlvbnRfdGF4X2Jyb2FkYC4gCgpgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCA8LSByMl9uYWthZ2F3YShzYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkIDwtIHRpYmJsZShlc3RpYW10ZSA9IGMoZml4ZWYoc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4ZWYoc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMilbMjozXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVmKHNhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMpWzNdKSkgCiAgCmNpX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDE8LWNvbmZpbnQoc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSkKY2lfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMjwtY29uZmludChzYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQyKQpjaV9zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQzPC1jb25maW50KHNhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMpCnJlc19zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgJTw+JSBtdXRhdGUobG93ZXJDTCA9IGMoY2lfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMVszOjUsMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaV9zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQyWzQ6NSwxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkM1s1LDFdKSkKcmVzX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCAlPD4lIG11dGF0ZSh1cHBlckNMID0gYyhjaV9zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxWzM6NSwyXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDJbNDo1LDJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaV9zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQzWzUsMl0pKQojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRuYW1lKSwgY29udF9nZW4ocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRuYW1lKSksCiAgRXN0aW1hdGUgPSByZXNfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkJGVzdGlhbXRlLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IHJlc19zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQkbG93ZXJDTCwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gcmVzX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCR1cHBlckNMLAogIGBWW2F1dGhvcnNdYCA9IGMoYXR0cihWYXJDb3JyKHNhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEpJGF1dGhvciwic3RkZGV2IileMiwgIHJlcChOQSwgNSkpLAogIGBWW3Jlc2lkdWFsc11gID1jKGF0dHIoVmFyQ29ycihzYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxKSwic2MiKV4yLCByZXAoTkEsIDUpKSwKICBgUjJgID0gYyhyMl9zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQkUjJfbWFyZ2luYWwsIHJlcChOQSwgNSkpKSAlPiUga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpIApgYGAKCgojIyMgU2Vuc2l0aXZpdHkgdGVzdCAyOiByZWFjaGluZyB0aGUgbGltaXRzCgojIyMgVGhlIHR5cGUgb2Ygc3ltYmlvc2lzOiBwYXJhc2l0aXNtIHZzLiBtdXR1YWxpc20KCioqU3VwcGxlbWVudGFyeSBUYWJsZSAzOioqClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4YW1wbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgc3ltYmlvbnRfdGF4X2Jyb2FkYC4gCgpgYGB7cn0KIyBzeW1iaW9zaXMKc2FfbGltaXRfc3ltYmlvc2lzMTwtZ2xtZXIobGltaXRfcmVhcmNoZWQgfiBzeW1iaW9zaXMgLSAxICsgKDEgfCBhdXRob3JzKSwgZmFtaWx5ID0gImJpbm9taWFsIiwgZGF0YSA9IGRhdCkKCiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9zYV9saW1pdF9zeW1iaW9zaXMgPC0gcjJfbmFrYWdhd2Eoc2FfbGltaXRfc3ltYmlvc2lzMSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKcmVzX3NhX2xpbWl0X3N5bWJpb3NpcyA8LSB0aWJibGUoZXN0aWFtdGUgPSBmaXhlZihzYV9saW1pdF9zeW1iaW9zaXMxKSkKICAKcmVzX3NhX2xpbWl0X3N5bWJpb3NpcyAlPD4lIG11dGF0ZShsb3dlckNMID0gKHRpZHkoc2FfbGltaXRfc3ltYmlvc2lzMSkkZXN0aW1hdGVbLTNdIC0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpZHkoc2FfbGltaXRfc3ltYmlvc2lzMSkkc3RkLmVycm9yWy0zXSpxbm9ybSgwLjk3NSkpKQpyZXNfc2FfbGltaXRfc3ltYmlvc2lzICU8PiUgbXV0YXRlKHVwcGVyQ0wgPSAodGlkeShzYV9saW1pdF9zeW1iaW9zaXMxKSRlc3RpbWF0ZVstM10gKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlkeShzYV9saW1pdF9zeW1iaW9zaXMxKSRzdGQuZXJyb3JbLTNdKnFub3JtKDAuOTc1KSkpCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBhcy5jaGFyYWN0ZXIocmVzX3N5bWJpb3NpczEkbmFtZSksCiAgRXN0aW1hdGUgPSByZXNfc2FfbGltaXRfc3ltYmlvc2lzJGVzdGlhbXRlLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IHJlc19zYV9saW1pdF9zeW1iaW9zaXMkbG93ZXJDTCwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gcmVzX3NhX2xpbWl0X3N5bWJpb3NpcyR1cHBlckNMLAogIGBWW2F1dGhvcnNdYCA9IGMoYXR0cihWYXJDb3JyKHNhX2xpbWl0X3N5bWJpb3NpczEpJGF1dGhvciwic3RkZGV2IileMiwgIHJlcChOQSwgMSkpLAogIGBSMmAgPSBjKHIyX3NhX2xpbWl0X3N5bWJpb3NpcyRSMl9tYXJnaW5hbCwgcmVwKE5BLCAxKSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgCgpgYGAKCiMjIyBUaGUgZWZmZWN0IG9mIGhvc3QgdGF4YQoKKipTdXBwbGVtZW50YXJ5IFRhYmxlIDM6KioKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhhbXBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBzeW1iaW9udF90YXhfYnJvYWRgLiAKCmBgYHtyfQojIGhvc3RfdGF4X2Jyb2FkCnNhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkMTwtZ2xtZXIobGltaXRfcmVhcmNoZWQgfiBob3N0X3RheF9icm9hZCAtIDEgICsgKDEgfCBhdXRob3JzKSwgZmFtaWx5ID0gImJpbm9taWFsIiwgZGF0YSA9IGRhdCkKCiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9zYV9saW1pdF9ob3N0X3RheF9icm9hZCA8LSByMl9uYWthZ2F3YShzYV9saW1pdF9ob3N0X3RheF9icm9hZDEpCgojIGdldHRpbmcgZXN0aW1hdGVzCnJlc19zYV9saW1pdF9ob3N0X3RheF9icm9hZCA8LSB0aWJibGUoZXN0aWFtdGUgPSBmaXhlZihzYV9saW1pdF9ob3N0X3RheF9icm9hZDEpKQogIApyZXNfc2FfbGltaXRfaG9zdF90YXhfYnJvYWQgJTw+JSBtdXRhdGUobG93ZXJDTCA9ICh0aWR5KHNhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkMSkkZXN0aW1hdGVbLTVdIC0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpZHkoc2FfbGltaXRfaG9zdF90YXhfYnJvYWQxKSRzdGQuZXJyb3JbLTVdKnFub3JtKDAuOTc1KSkpCnJlc19zYV9saW1pdF9ob3N0X3RheF9icm9hZCAlPD4lIG11dGF0ZSh1cHBlckNMID0gKHRpZHkoc2FfbGltaXRfaG9zdF90YXhfYnJvYWQxKSRlc3RpbWF0ZVstNV0gKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlkeShzYV9saW1pdF9ob3N0X3RheF9icm9hZDEpJHN0ZC5lcnJvclstNV0qcW5vcm0oMC45NzUpKSkKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGFzLmNoYXJhY3RlcihyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSRuYW1lKSwKICBFc3RpbWF0ZSA9IHJlc19zYV9saW1pdF9ob3N0X3RheF9icm9hZCRlc3RpYW10ZSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSByZXNfc2FfbGltaXRfaG9zdF90YXhfYnJvYWQkbG93ZXJDTCwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gcmVzX3NhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkJHVwcGVyQ0wsCiAgYFZbYXV0aG9yc11gID0gYyhhdHRyKFZhckNvcnIoc2FfbGltaXRfaG9zdF90YXhfYnJvYWQxKSRhdXRob3IsInN0ZGRldiIpXjIsICByZXAoTkEsIDMpKSwKICBgUjJgID0gYyhyMl9zYV9saW1pdF9ob3N0X3RheF9icm9hZCRSMl9tYXJnaW5hbCwgcmVwKE5BLCAzKSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgCgpgYGAKCgojIyMgVGhlIGVmZmVjdCBvZiB0aGUgbW9kZWwgb2YgdHJhbnNtaXNzaW9uCgoqKlN1cHBsZW1lbnRhcnkgVGFibGUgMzoqKgpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleGFtcGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYHN5bWJpb250X3RheF9icm9hZGAuIAoKYGBge3J9CiMgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQKc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxPC1nbG1lcihsaW1pdF9yZWFyY2hlZCB+IG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkIC0gMSArICgxIHwgYXV0aG9ycyksIGZhbWlseSA9ICJiaW5vbWlhbCIsIGRhdGEgPSBkYXQpCgojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPC0gcjJfbmFrYWdhd2Eoc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPC0gdGliYmxlKGVzdGlhbXRlID0gZml4ZWYoc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxKSkKICAKcmVzX3NhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkICU8PiUgbXV0YXRlKGxvd2VyQ0wgPSAodGlkeShzYV9saW1pdF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEpJGVzdGltYXRlWy00XSAtCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWR5KHNhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSkkc3RkLmVycm9yWy00XSpxbm9ybSgwLjk3NSkpKQpyZXNfc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgJTw+JSBtdXRhdGUodXBwZXJDTCA9ICh0aWR5KHNhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSkkZXN0aW1hdGVbLTRdICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpZHkoc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxKSRzdGQuZXJyb3JbLTRdKnFub3JtKDAuOTc1KSkpCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBhcy5jaGFyYWN0ZXIocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRuYW1lKSwKICBFc3RpbWF0ZSA9IHJlc19zYV9saW1pdF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCRlc3RpYW10ZSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSByZXNfc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQkbG93ZXJDTCwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gcmVzX3NhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkJHVwcGVyQ0wsCiAgYFZbYXV0aG9yc11gID0gYyhhdHRyKFZhckNvcnIoc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxKSRhdXRob3IsInN0ZGRldiIpXjIsICByZXAoTkEsIDIpKSwKICBgUjJgID0gYyhyMl9zYV9saW1pdF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCRSMl9tYXJnaW5hbCwgcmVwKE5BLCAyKSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgCmBgYAoKIyMjIFJlY29tbWVuZGF0aW9uCiogdGhleSBuZWVkIHRvIHJ1biBtb3JlIHNpbXVhdGlvbnMgc28gdGhleSBkbyBub3QgbWF4IG91dCEKKiByZWFuYWx5c2lzIG9mIGVhcmxpZXIgdHJlZXMgYXJlIG5lY2Vzc2FyeTsgZ2V0dGluZyBvbGRlciBvciB1cGRhdGVkIHRyZWVzIGFyZSByZXF1aXJlZAoqIG5ldyBzdHVkaWVzIHNob3VsZCBwcm92aWRlIGFsbCBkYXRhIGF2YWlhYmxlIG9ubGluZSBzbyB0aGF0IGZ1dHVyZSBhbmFseXNpcyBjYW4gaW5jb3JwcmF0ZSBhbGwgYXZhaWFibGUgZGF0YQoKIyMgQWNrbm93bGVkZ2VtZW50CgpNdWNoIG9mIGNvZGluZyBtYXRlcmlhbHMgaGF2ZSBiZWVuIGJvcnJvd2VkIGZyb20gaAoKIyMgUmVmZXJlcmVuY2VzCgojIyBJbmZvcm1hdGlvbiBmb3IgdGhpcyBSIHNlc3Npb24KCmBgYHtyfQpzZXNzaW9uSW5mbygpICU+JSBwYW5kZXIoKQpgYGAK